diff --git a/src/core/evaluateDot.go b/src/core/evaluateDot.go index 49b5a7b..a1c2a6e 100644 --- a/src/core/evaluateDot.go +++ b/src/core/evaluateDot.go @@ -37,7 +37,7 @@ func (f *Function) evaluateDot(expr *expression.Expression) (ssa.Value, error) { imp.Used.Add(1) } - return f.evaluateDotPackage(pkg, rightText, expr) + return f.evaluatePackageMember(pkg, rightText, expr) case *ssa.Struct: field := types.Unwrap(leftValue.Typ).(*types.Struct).FieldByName(rightText) diff --git a/src/core/evaluateIdentifier.go b/src/core/evaluateIdentifier.go new file mode 100644 index 0000000..9d32f93 --- /dev/null +++ b/src/core/evaluateIdentifier.go @@ -0,0 +1,54 @@ +package core + +import ( + "slices" + + "git.urbach.dev/cli/q/src/errors" + "git.urbach.dev/cli/q/src/expression" + "git.urbach.dev/cli/q/src/ssa" +) + +// evaluateIdentifier converts an identifier to an SSA value. +func (f *Function) evaluateIdentifier(expr *expression.Expression) (ssa.Value, error) { + name := expr.Token.String(f.File.Bytes) + + switch name { + case "false": + v := f.Append(&ssa.Bool{ + Bool: false, + Source: expr.Source(), + }) + + return v, nil + + case "true": + v := f.Append(&ssa.Bool{ + Bool: true, + Source: expr.Source(), + }) + + return v, nil + } + + value, exists := f.Block().FindIdentifier(name) + + if exists { + for _, p := range f.Block().Protected { + if slices.Contains(p, value) { + return nil, errors.New(&ErrorNotChecked{Identifier: name}, f.File, expr.Token.Position) + } + } + + return value, nil + } + + if name != f.File.Package { + _, exists := f.Env.Packages[name] + + if exists { + return &ssa.Package{Name: name}, nil + } + } + + return f.evaluatePackageMember(f.Env.Packages[f.File.Package], name, expr) +} \ No newline at end of file diff --git a/src/core/evaluateLeaf.go b/src/core/evaluateLeaf.go new file mode 100644 index 0000000..56510d0 --- /dev/null +++ b/src/core/evaluateLeaf.go @@ -0,0 +1,24 @@ +package core + +import ( + "git.urbach.dev/cli/q/src/errors" + "git.urbach.dev/cli/q/src/expression" + "git.urbach.dev/cli/q/src/ssa" + "git.urbach.dev/cli/q/src/token" +) + +// evaluateLeaf converts a leaf expression to an SSA value. +func (f *Function) evaluateLeaf(expr *expression.Expression) (ssa.Value, error) { + switch expr.Token.Kind { + case token.Identifier: + return f.evaluateIdentifier(expr) + + case token.Number, token.Rune: + return f.evaluateNumber(expr) + + case token.String: + return f.evaluateString(expr) + } + + return nil, errors.New(InvalidExpression, f.File, expr.Token.Position) +} \ No newline at end of file diff --git a/src/core/evaluateNumber.go b/src/core/evaluateNumber.go new file mode 100644 index 0000000..91c4d11 --- /dev/null +++ b/src/core/evaluateNumber.go @@ -0,0 +1,22 @@ +package core + +import ( + "git.urbach.dev/cli/q/src/expression" + "git.urbach.dev/cli/q/src/ssa" +) + +// evaluateNumber converts a numeric expression to an SSA value. +func (f *Function) evaluateNumber(expr *expression.Expression) (ssa.Value, error) { + number, err := toNumber(expr.Token, f.File) + + if err != nil { + return nil, err + } + + v := f.Append(&ssa.Int{ + Int: number, + Source: expr.Source(), + }) + + return v, nil +} \ No newline at end of file diff --git a/src/core/evaluateDotPackage.go b/src/core/evaluatePackageMember.go similarity index 85% rename from src/core/evaluateDotPackage.go rename to src/core/evaluatePackageMember.go index 48512d6..27cd619 100644 --- a/src/core/evaluateDotPackage.go +++ b/src/core/evaluatePackageMember.go @@ -6,8 +6,8 @@ import ( "git.urbach.dev/cli/q/src/ssa" ) -// evaluateDotPackage converts a pkg.something expression to an SSA value. -func (f *Function) evaluateDotPackage(pkg *Package, rightText string, expr *expression.Expression) (ssa.Value, error) { +// evaluatePackageMember converts a pkg.something expression to an SSA value. +func (f *Function) evaluatePackageMember(pkg *Package, rightText string, expr *expression.Expression) (ssa.Value, error) { constant, exists := pkg.Constants[rightText] if exists { diff --git a/src/core/evaluateString.go b/src/core/evaluateString.go new file mode 100644 index 0000000..4e7b5f6 --- /dev/null +++ b/src/core/evaluateString.go @@ -0,0 +1,33 @@ +package core + +import ( + "git.urbach.dev/cli/q/src/expression" + "git.urbach.dev/cli/q/src/ssa" + "git.urbach.dev/cli/q/src/types" +) + +// evaluateString converts a string expression to an SSA value. +func (f *Function) evaluateString(expr *expression.Expression) (ssa.Value, error) { + data := expr.Token.Bytes(f.File.Bytes) + data = unescape(data) + + v := &ssa.Struct{ + Typ: types.String, + Source: expr.Source(), + } + + length := f.Append(&ssa.Int{ + Int: len(data), + Structure: v, + Source: expr.Source(), + }) + + pointer := f.Append(&ssa.Bytes{ + Bytes: data, + Structure: v, + Source: expr.Source(), + }) + + v.Arguments = []ssa.Value{pointer, length} + return v, nil +} \ No newline at end of file diff --git a/src/core/evaluateToken.go b/src/core/evaluateToken.go deleted file mode 100644 index fec0208..0000000 --- a/src/core/evaluateToken.go +++ /dev/null @@ -1,99 +0,0 @@ -package core - -import ( - "slices" - - "git.urbach.dev/cli/q/src/errors" - "git.urbach.dev/cli/q/src/expression" - "git.urbach.dev/cli/q/src/ssa" - "git.urbach.dev/cli/q/src/token" - "git.urbach.dev/cli/q/src/types" -) - -// evaluateLeaf converts a leaf expression to an SSA value. -func (f *Function) evaluateLeaf(expr *expression.Expression) (ssa.Value, error) { - switch expr.Token.Kind { - case token.Identifier: - name := expr.Token.String(f.File.Bytes) - - switch name { - case "false": - v := f.Append(&ssa.Bool{ - Bool: false, - Source: expr.Source(), - }) - - return v, nil - - case "true": - v := f.Append(&ssa.Bool{ - Bool: true, - Source: expr.Source(), - }) - - return v, nil - } - - value, exists := f.Block().FindIdentifier(name) - - if exists { - for _, p := range f.Block().Protected { - if slices.Contains(p, value) { - return nil, errors.New(&ErrorNotChecked{Identifier: name}, f.File, expr.Token.Position) - } - } - - return value, nil - } - - if name != f.File.Package { - _, exists := f.Env.Packages[name] - - if exists { - return &ssa.Package{Name: name}, nil - } - } - - return f.evaluateDotPackage(f.Env.Packages[f.File.Package], name, expr) - - case token.Number, token.Rune: - number, err := toNumber(expr.Token, f.File) - - if err != nil { - return nil, err - } - - v := f.Append(&ssa.Int{ - Int: number, - Source: expr.Source(), - }) - - return v, nil - - case token.String: - data := expr.Token.Bytes(f.File.Bytes) - data = unescape(data) - - v := &ssa.Struct{ - Typ: types.String, - Source: expr.Source(), - } - - length := f.Append(&ssa.Int{ - Int: len(data), - Structure: v, - Source: expr.Source(), - }) - - pointer := f.Append(&ssa.Bytes{ - Bytes: data, - Structure: v, - Source: expr.Source(), - }) - - v.Arguments = []ssa.Value{pointer, length} - return v, nil - } - - return nil, errors.New(InvalidExpression, f.File, expr.Token.Position) -} \ No newline at end of file