merge: solved a lot of conflicts caused by an incorect commit removal

This commit is contained in:
Celestino Amoroso 2024-04-13 05:47:10 +02:00
commit b9ea96f649
8 changed files with 58 additions and 10 deletions

View File

@ -135,6 +135,9 @@ func main() {
} }
---- ----
=== Concepts and terminology
#TODO#
=== Data types === Data types
_Expr_ supports numerical, string, relational, boolean expressions, and mixed-type lists. _Expr_ supports numerical, string, relational, boolean expressions, and mixed-type lists.
@ -260,7 +263,15 @@ _Expr_ supports list of mixed-type values, also specified by normal expressions.
|=== |===
=== Variables === Variables
#TODO: variables# A variable is an identifier with an assigned value. Variables are stored in the object that implements the _ExprContext_ interface.
.Examples
[source,go]
----
a=1
x = 5.2 * (9-3)
x = 1; y = 2*x
----
=== Other operations === Other operations
@ -346,12 +357,15 @@ The table below shows all supported operators by decreasing priorities.
.2+|*AND*| [blue]`and` | _Infix_ | _and_ | _boolean_ "and" _boolean_ -> _boolean_ .2+|*AND*| [blue]`and` | _Infix_ | _and_ | _boolean_ "and" _boolean_ -> _boolean_
| [blue]`&&` | _Infix_ | _and_ | _boolean_ "&&" _boolean_ -> _boolean_ | [blue]`&&` | _Infix_ | _and_ | _boolean_ "&&" _boolean_ -> _boolean_
.2+|*OR*| [blue]`or` | _Infix_ | _or_ | _boolean_ "or" _boolean_ -> _boolean_ .2+|*OR*| [blue]`or` | _Infix_ | _or_ | _boolean_ "or" _boolean_ -> _boolean_
| [blue]`||` | _Infix_ | _or_ | _boolean_ "||" _boolean_ -> _boolean_ | [blue]`\|\|` | _Infix_ | _or_ | _boolean_ "\|\|" _boolean_ -> _boolean_
.1+|*ASSIGN*| [blue]`=` | _Infix_ | _assignment_ | _identifier_ "=" _any_ -> _any_ .1+|*ASSIGN*| [blue]`=` | _Infix_ | _assignment_ | _identifier_ "=" _any_ -> _any_
.1+|*BUT*| [blue]`but` | _Infix_ | _but_ | _any_ "but" _any_ -> _any_ .1+|*BUT*| [blue]`but` | _Infix_ | _but_ | _any_ "but" _any_ -> _any_
|=== |===
=== Functions === Functions
Functions in _Expr_ are very similar to functions in many programming languages.
In _Expr_ functions compute values in a local context (scope) that do not make effects on the calling context. This is the normal behavior. Using the reference operator [blue]`@` it is possibile to export local definition to the calling context.
==== Function calls ==== Function calls
#TODO: function calls operations# #TODO: function calls operations#
@ -359,8 +373,13 @@ The table below shows all supported operators by decreasing priorities.
==== Function definitions ==== Function definitions
#TODO: function definitions operations# #TODO: function definitions operations#
==== Builtins === Builtins
#TODO: builtins# #TODO: builtins#
==== Builtin functions
==== [blue]_import()_
[blue]_import([grey]#<source-file>#)_ loads the multi-expression contained in the specified source and returns its value.

2
ast.go
View File

@ -119,7 +119,7 @@ func (self *ast) eval(ctx ExprContext, preset bool) (result any, err error) {
if self.forest != nil { if self.forest != nil {
for _, root := range self.forest { for _, root := range self.forest {
if result, err = root.compute(ctx); err == nil { if result, err = root.compute(ctx); err == nil {
ctx.SetVar(ControlLastResult, result) ctx.setVar(ControlLastResult, result)
} else { } else {
//err = fmt.Errorf("error in expression nr %d: %v", i+1, err) //err = fmt.Errorf("error in expression nr %d: %v", i+1, err)
break break

View File

@ -33,6 +33,7 @@ type ExprContext interface {
Clone() ExprContext Clone() ExprContext
GetVar(varName string) (value any, exists bool) GetVar(varName string) (value any, exists bool)
SetVar(varName string, value any) SetVar(varName string, value any)
setVar(varName string, value any)
EnumVars(func(name string) (accept bool)) (varNames []string) EnumVars(func(name string) (accept bool)) (varNames []string)
EnumFuncs(func(name string) (accept bool)) (funcNames []string) EnumFuncs(func(name string) (accept bool)) (funcNames []string)
GetFuncInfo(name string) ExprFunc GetFuncInfo(name string) ExprFunc

View File

@ -57,7 +57,7 @@ func exportVar(ctx ExprContext, name string, value any) {
if name[0] == '@' { if name[0] == '@' {
name = name[1:] name = name[1:]
} }
ctx.SetVar(name, value) ctx.setVar(name, value)
} }
func exportFunc(ctx ExprContext, name string, info ExprFunc) { func exportFunc(ctx ExprContext, name string, info ExprFunc) {
@ -89,9 +89,9 @@ type funcDefFunctor struct {
func (functor *funcDefFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) { func (functor *funcDefFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) {
for i, p := range functor.params { for i, p := range functor.params {
if i < len(args) { if i < len(args) {
ctx.SetVar(p, args[i]) ctx.setVar(p, args[i])
} else { } else {
ctx.SetVar(p, nil) ctx.setVar(p, nil)
} }
} }
result, err = functor.expr.eval(ctx, false) result, err = functor.expr.eval(ctx, false)

View File

@ -31,7 +31,7 @@ func evalAssign(ctx ExprContext, self *term) (v any, err error) {
if functor, ok := v.(Functor); ok { if functor, ok := v.(Functor); ok {
ctx.RegisterFunc(leftTerm.source(), functor, 0, -1) ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
} else { } else {
ctx.SetVar(leftTerm.tk.source, v) ctx.setVar(leftTerm.tk.source, v)
} }
} }
return return

View File

@ -75,7 +75,7 @@ func evalAssignCoalesce(ctx ExprContext, self *term) (v any, err error) {
err = errCoalesceNoFunc(self.children[1]) err = errCoalesceNoFunc(self.children[1])
} else { } else {
v = rightValue v = rightValue
ctx.SetVar(leftTerm.source(), rightValue) ctx.setVar(leftTerm.source(), rightValue)
} }
} }
return return

View File

@ -1,6 +1,8 @@
// simple-var-store.go // simple-var-store.go
package expr package expr
import "fmt"
type SimpleVarStore struct { type SimpleVarStore struct {
varStore map[string]any varStore map[string]any
} }
@ -23,10 +25,18 @@ func (ctx *SimpleVarStore) GetVar(varName string) (v any, exists bool) {
return return
} }
func (ctx *SimpleVarStore) SetVar(varName string, value any) { func (ctx *SimpleVarStore) setVar(varName string, value any) {
ctx.varStore[varName] = value ctx.varStore[varName] = value
} }
func (ctx *SimpleVarStore) SetVar(varName string, value any) {
if allowedValue, ok := fromGenericAny(value); ok {
ctx.varStore[varName] = allowedValue
} else {
panic(fmt.Errorf("unsupported type %T of value %v", value, value))
}
}
func (ctx *SimpleVarStore) EnumVars(acceptor func(name string) (accept bool)) (varNames []string) { func (ctx *SimpleVarStore) EnumVars(acceptor func(name string) (accept bool)) (varNames []string) {
varNames = make([]string, 0) varNames = make([]string, 0)
for name := range ctx.varStore { for name := range ctx.varStore {

View File

@ -73,6 +73,8 @@ func anyInteger(v any) (i int64, ok bool) {
i = int64(intval) i = int64(intval)
case uint16: case uint16:
i = int64(intval) i = int64(intval)
case uint64:
i = int64(intval)
case uint32: case uint32:
i = int64(intval) i = int64(intval)
case int8: case int8:
@ -89,6 +91,22 @@ func anyInteger(v any) (i int64, ok bool) {
return return
} }
func fromGenericAny(v any) (exprAny any, ok bool) {
if exprAny, ok = v.(bool); ok {
return
}
if exprAny, ok = v.(string); ok {
return
}
if exprAny, ok = anyInteger(v); ok {
return
}
if exprAny, ok = anyFloat(v); ok {
return
}
return
}
func anyFloat(v any) (float float64, ok bool) { func anyFloat(v any) (float float64, ok bool) {
ok = true ok = true
switch floatval := v.(type) { switch floatval := v.(type) {