Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0200f8d
Add struct declaration parsing (https://github.com/monstermichl/TypeS…
monstermichl Sep 6, 2025
b70c2b6
Fix test
monstermichl Sep 6, 2025
82d5386
Add struct declaration struct and default value for structs (https://…
monstermichl Sep 6, 2025
efa6d1f
Add first draft of struct definition (https://github.com/monstermichl…
monstermichl Sep 7, 2025
28aad3d
Start struct assignment implementation (https://github.com/monstermic…
monstermichl Sep 7, 2025
ca6d97b
Get struct evaluation working in Batch (https://github.com/monstermic…
monstermichl Sep 9, 2025
6dbf416
Get struct evaluation working in Bash (https://github.com/monstermich…
monstermichl Sep 9, 2025
5ca240c
Fix nested struct check (https://github.com/monstermichl/TypeShell/is…
monstermichl Sep 9, 2025
b93fabc
Improve error messages (https://github.com/monstermichl/TypeShell/iss…
monstermichl Sep 9, 2025
77e1194
Improve error message (https://github.com/monstermichl/TypeShell/issu…
monstermichl Sep 9, 2025
371b7e0
Completely redesign type handling (https://github.com/monstermichl/Ty…
monstermichl Sep 11, 2025
6d68113
Improve type declaration and fix struct assignment (https://github.co…
monstermichl Sep 11, 2025
077c57d
Get struct default values in slices working (https://github.com/monst…
monstermichl Sep 11, 2025
425301b
Implement first draft of struct initialization with values (https://g…
monstermichl Sep 12, 2025
3fe936a
Fix double name check (https://github.com/monstermichl/TypeShell/issu…
monstermichl Sep 12, 2025
da1c7e1
Add tests (https://github.com/monstermichl/TypeShell/issues/51)
monstermichl Sep 12, 2025
b33d488
Update .gitignore
monstermichl Sep 12, 2025
b4e8324
Copy struct values to param before calling a function (probably needs…
monstermichl Sep 12, 2025
68c35da
Only evaluate variables if they are not already evaluated (https://gi…
monstermichl Sep 12, 2025
28e975c
Fix struct field copying (https://github.com/monstermichl/TypeShell/i…
monstermichl Sep 12, 2025
be8bb3e
Add tests (https://github.com/monstermichl/TypeShell/issues/51)
monstermichl Sep 12, 2025
b48e584
Do some renaming (https://github.com/monstermichl/TypeShell/issues/51)
monstermichl Sep 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
examples/*
!examples/*.tsh
ext
tests/std
121 changes: 94 additions & 27 deletions converters/bash/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@ import (
"github.com/monstermichl/typeshell/transpiler"
)

type helperName = string

const (
sliceAssignmentHelper helperName = "_sah" // Slice assignment
sliceCopyHelper helperName = "_sch" // Slice copy
structAssignmentHelper helperName = "_stah" // Struct assignment
stringSubscriptHelper helperName = "_stsh" // String subscript
)

type funcInfo struct {
name string
}

type converter struct {
interpreter string
startCode []string
code []string
varCounter int
forCounter int
funcs []funcInfo
funcCounter int
sliceAssignmentHelperRequired bool
sliceCopyHelperRequired bool
stringSubscriptHelperRequired bool
interpreter string
startCode []string
code []string
varCounter int
forCounter int
funcs []funcInfo
funcCounter int
sliceAssignmentHelperRequired bool
structAssignmentHelperRequired bool
sliceCopyHelperRequired bool
stringSubscriptHelperRequired bool
}

func New() *converter {
Expand Down Expand Up @@ -62,7 +72,7 @@ func (c *converter) ProgramEnd() error {
// $2: Assignment index
// $3: Assignment value
// $4: Default value
c.addHelper("slice assignment", "_sah",
c.addHelper("slice assignment", sliceAssignmentHelper,
"local _i=${2}",
fmt.Sprintf(`local _l=%s`, c.sliceLenString("${1}")),
`for ((_c=${_l};_c<${_i};_c++)); do`,
Expand All @@ -73,7 +83,7 @@ func (c *converter) ProgramEnd() error {
}

if c.sliceCopyHelperRequired {
c.addHelper("slice copy", "_sch",
c.addHelper("slice copy", sliceCopyHelper,
"local _i=0",
fmt.Sprintf(`local _l=%s`, c.sliceLenString("${2}")),
"local _n=$(eval \"echo \\${${1}}\")",
Expand All @@ -85,8 +95,17 @@ func (c *converter) ProgramEnd() error {
)
}

if c.structAssignmentHelperRequired {
// $1: Struct name
// $2: Assignment field
// $3: Assignment value
c.addHelper("struct assignment", structAssignmentHelper,
c.structAssignmentString("${1}", "${2}", "${3}", false),
)
}

if c.stringSubscriptHelperRequired {
c.addHelper("substring", "_ssh",
c.addHelper("substring", stringSubscriptHelper,
`_ls=$((${2}))`,
`_ll=$(((${3}-${2})+1))`,
`_ret="${1:${_ls}:${_ll}}"`,
Expand All @@ -106,7 +125,13 @@ func (c *converter) VarAssignment(name string, value string, global bool) error

func (c *converter) SliceAssignment(name string, index string, value string, defaultValue string, global bool) error {
c.sliceAssignmentHelperRequired = true
c.addLine(fmt.Sprintf(`_sah %s %s "%s" "%s"`, c.varEvaluationString(name, global), index, value, defaultValue))
c.callFunc(sliceAssignmentHelper, c.varEvaluationString(name, global), index, value, defaultValue)
return nil
}

func (c *converter) StructAssignment(name string, field string, value string, global bool) error {
c.structAssignmentHelperRequired = true
c.callFunc(structAssignmentHelper, c.varEvaluationString(name, global), field, value)
return nil
}

Expand Down Expand Up @@ -259,8 +284,8 @@ func (c *converter) BinaryOperation(left string, operator parser.BinaryOperator,
return notAllowedError()
}

switch valueType.DataType() {
case parser.DATA_TYPE_INTEGER:
switch valueType.Type().ElementaryType().Kind() {
case parser.TypeKindInt:
switch operator {
case parser.BINARY_OPERATOR_MULTIPLICATION,
parser.BINARY_OPERATOR_DIVISION,
Expand All @@ -272,7 +297,7 @@ func (c *converter) BinaryOperation(left string, operator parser.BinaryOperator,
return notAllowedError()
}
c.VarAssignment(helper, fmt.Sprintf("$((%s%s%s))", left, operator, right), false) // Backslash is required for * operator to prevent pattern expansion (https://www.shell-tips.com/bash/math-arithmetic-calculation/#using-the-expr-command-line).
case parser.DATA_TYPE_STRING:
case parser.TypeKindString:
switch operator {
case parser.BINARY_OPERATOR_ADDITION:
c.VarAssignment(helper, fmt.Sprintf("\"%s%s\"", left, right), false)
Expand All @@ -289,15 +314,15 @@ func (c *converter) Comparison(left string, operator parser.CompareOperator, rig
var operatorString string

if !valueType.IsSlice() {
switch valueType.DataType() {
case parser.DATA_TYPE_BOOLEAN:
switch valueType.Type().ElementaryType().Kind() {
case parser.TypeKindBool:
switch operator {
case parser.COMPARE_OPERATOR_EQUAL:
operatorString = "-eq"
case parser.COMPARE_OPERATOR_NOT_EQUAL:
operatorString = "-ne"
}
case parser.DATA_TYPE_INTEGER:
case parser.TypeKindInt:
switch operator {
case parser.COMPARE_OPERATOR_EQUAL:
operatorString = "-eq"
Expand All @@ -312,7 +337,7 @@ func (c *converter) Comparison(left string, operator parser.CompareOperator, rig
case parser.COMPARE_OPERATOR_LESS_OR_EQUAL:
operatorString = "-le"
}
case parser.DATA_TYPE_STRING:
case parser.TypeKindString:
switch operator {
case parser.COMPARE_OPERATOR_EQUAL:
operatorString = "=="
Expand Down Expand Up @@ -376,9 +401,7 @@ func (c *converter) VarEvaluation(name string, valueUsed bool, global bool) (str
}

func (c *converter) SliceInstantiation(values []string, valueUsed bool) (string, error) {
c.addLine(fmt.Sprintf(`_dvc=$((%s+1))`, c.varEvaluationString("_dvc", true))) // Dynamic variable counter.
helper := c.nextHelperVar()
c.VarAssignment(helper, fmt.Sprintf(`_dv%s`, c.varEvaluationString("_dvc", true)), false)
helper := c.nextDynamicHelperVar()

if len(values) > 0 {
vals := ""
Expand Down Expand Up @@ -408,10 +431,30 @@ func (c *converter) SliceLen(name string, valueUsed bool) (string, error) {
return c.VarEvaluation(helper, valueUsed, false)
}

func (c *converter) StructInitialization(values []transpiler.StructValue, valueUsed bool) (string, error) {
helper := c.nextDynamicHelperVar()

for _, value := range values {
c.addLine(c.structAssignmentString(c.varEvaluationString(helper, false), value.Name(), value.Value(), false))
}
return c.varEvaluationString(helper, false), nil
}

func (c *converter) StructEvaluation(name string, field string, valueUsed bool) (string, error) {
helper := c.nextHelperVar()

c.VarAssignment(
helper,
c.structEvaluationString(name, field),
false,
)
return c.VarEvaluation(helper, valueUsed, false)
}

func (c *converter) StringSubscript(value string, startIndex string, endIndex string, valueUsed bool) (string, error) {
helper := c.nextHelperVar()

c.addLine(fmt.Sprintf(`_ssh "%s" %s %s`, value, startIndex, endIndex))
c.callFunc(stringSubscriptHelper, value, startIndex, endIndex)
c.VarAssignment(helper, c.varEvaluationString("_ret", true), false) // https://www.baeldung.com/linux/bash-substring#1-using-thecut-command
c.stringSubscriptHelperRequired = true

Expand Down Expand Up @@ -511,7 +554,7 @@ func (c *converter) Input(prompt string, valueUsed bool) (string, error) {
func (c *converter) Copy(destination string, source string, valueUsed bool, global bool) (string, error) {
destination = c.varName(destination, global)

c.addLine(fmt.Sprintf("_sch %s %s", destination, source))
c.callFunc(sliceCopyHelper, destination, source)
c.sliceAssignmentHelperRequired = true
c.sliceCopyHelperRequired = true

Expand Down Expand Up @@ -541,6 +584,10 @@ func (c *converter) ReadFile(path string, valueUsed bool) (string, error) {
return c.VarEvaluation(helper, valueUsed, false)
}

func (c *converter) callFunc(name string, args ...string) {
c.addLine(fmt.Sprintf(`%s "%s"`, name, strings.Join(args, `" "`)))
}

func (c *converter) mustCurrentForVar() string {
return fmt.Sprintf("_fv%d", c.forCounter)
}
Expand All @@ -567,14 +614,22 @@ func (c *converter) varAssignmentString(name string, value string, global bool)
}

func (c *converter) varEvaluationString(name string, global bool) string {
return fmt.Sprintf("${%s}", c.varName(name, global))
// Only evaluate if it's not already evaluated.
if !strings.HasPrefix(name, "${") && !strings.HasSuffix(name, "}") {
return fmt.Sprintf("${%s}", c.varName(name, global))
}
return name
}

func (c *converter) sliceAssignmentString(name string, index string, value string, global bool) string {
c.sliceAssignmentHelperRequired = true
return fmt.Sprintf(`eval "%s[%s]=\"%s\""`, name, index, value)
}

func (c *converter) structAssignmentString(name string, field string, value string, global bool) string {
return fmt.Sprintf(`eval "%s_%s=\"%s\""`, name, field, value)
}

func (c *converter) sliceEvaluationString(name string, index string) string {
return fmt.Sprintf(`$(eval "echo \${%s[%s]}")`, name, index)
}
Expand All @@ -583,6 +638,10 @@ func (c *converter) sliceLenString(name string) string {
return fmt.Sprintf(`$(eval "echo \${#%s[@]}")`, name)
}

func (c *converter) structEvaluationString(name string, field string) string {
return fmt.Sprintf(`$(eval "echo \${%s_%s}")`, c.varEvaluationString(name, false), field)
}

func (c *converter) ifStart(condition string, startWord string) error {
c.addLine(fmt.Sprintf("%s [ %s -eq %s ]; then", startWord, condition, transpiler.BoolToString(true)))
return nil
Expand Down Expand Up @@ -616,3 +675,11 @@ func (c *converter) nextHelperVar() string {

return helperVar
}

func (c *converter) nextDynamicHelperVar() string {
c.addLine(fmt.Sprintf(`_dvc=$((%s+1))`, c.varEvaluationString("_dvc", true))) // Dynamic variable counter.
helper := c.nextHelperVar()
c.VarAssignment(helper, fmt.Sprintf(`_dv%s`, c.varEvaluationString("_dvc", true)), false)

return helper
}
Loading
Loading