From 9222a5a73923407f6c0ab2c0d40bb58114b7a6ec Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Fri, 8 Apr 2022 02:20:14 -0400 Subject: [EVAL] Control Flow + Added support for loop and if + Added support for break statements inside CF blocks + Fixed a bug with floats not parsing in specific cases --- examples/basic.tnsl | 17 ++++- src/texec/eval.go | 171 +++++++++++++++++++++++++++++++++++-------- src/tparse/tree-statement.go | 5 +- 3 files changed, 158 insertions(+), 35 deletions(-) diff --git a/examples/basic.tnsl b/examples/basic.tnsl index 71d784d..b19532f 100644 --- a/examples/basic.tnsl +++ b/examples/basic.tnsl @@ -1,3 +1,18 @@ /; main [int] - ;return 0 + + ;int i = 0 + ;float f = 0.25 + + /; loop (i < 2) + + ;i = i + 1 + + /; if (f < 1) + + ;i = i + 1 + ;break + ;/ + ;/ + + ;return i ;/ diff --git a/src/texec/eval.go b/src/texec/eval.go index 50e1bf3..2da654a 100644 --- a/src/texec/eval.go +++ b/src/texec/eval.go @@ -435,7 +435,7 @@ func getLiteralType(v tparse.Node) TType { return tStruct } else if v.Data.Data == "true" || v.Data.Data == "false" { return tBool - } else if v.Data.Data[0] == '0' { + } else if len(v.Data.Data) > 2 && v.Data.Data[0] == '0' && v.Data.Data[1] != '.' { return tInt } else { return tFloat @@ -593,6 +593,8 @@ func resolveArtifactCall(a TArtifact, params []TVariable) TVariable { } } + + return null } @@ -659,6 +661,11 @@ func evalIndex(n tparse.Node, v *TVariable) *interface{} { return out } +// Evaluate Call and Index +func evalCAI(v tparse.Node, art TArtifact, ctx *VarMap) *TVariable { + return &null +} + func evalDotChain(v tparse.Node, ctx *VarMap, wk *TVariable) *TVariable { var wrvm *VarMap wrvm = ctx @@ -708,6 +715,20 @@ func setVal(v tparse.Node, ctx *VarMap, val *TVariable) *TVariable { } var set *interface{} = &(wrk.Data) + + for ;; { + if len(vwk.Sub) > 0 { + + } + + if v.Data.Data == "." { + vwk = v.Sub[0] + + continue + } + + break + } (*set) = convertValPS((*wrk).Type, 0, val.Data) @@ -735,19 +756,7 @@ func evalValue(v tparse.Node, ctx *VarMap) *TVariable { return &TVariable{t, getLiteral(v, t)} case tparse.DEFWORD: if len(v.Sub) > 0 { - if v.Sub[0].Data.Data == "index" { - return evalIndex(v, resolveArtifact(TArtifact{[]string{}, v.Data.Data}, ctx)) - } else if v.Sub[0].Data.Data == "call" { - params := []TVariable{} - - for i := 0; i < len(v.Sub[0].Sub); i++ { - params = append(params, *evalValue(v.Sub[0].Sub[i], ctx)) - } - - out := evalBlock(*searchNode(TArtifact{[]string{}, v.Data.Data}), params) - - return &out - } + return evalCAI(v, TArtifact{[]string{}, v.Data.Data}, ctx) } return resolveArtifact(TArtifact{[]string{}, v.Data.Data}, ctx) @@ -835,17 +844,123 @@ func evalDef(v tparse.Node, ctx *VarMap) { } // Eval a control flow -func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable) { - //scopeVars := []string{} - return false, null +func evalCF(v tparse.Node, ctx *VarMap) (bool, TVariable, int) { + + loop := true + cond := tparse.Node{tparse.Token{tparse.LITERAL, "true", -1, -1}, []tparse.Node{}} + var after *tparse.Node = nil + + if v.Sub[0].Data.Data == "bdef" { + var before *tparse.Node + + for i := 0; i < len(v.Sub[0].Sub); i++ { + switch v.Sub[0].Sub[i].Data.Data { + case "if": + loop = false + case "()": + before = &(v.Sub[0].Sub[i]) + case "[]": + after = &(v.Sub[0].Sub[i]) + } + } + + for i := 0; i < len(before.Sub); i++ { + switch before.Sub[i].Data.Data { + case "define": + evalDef(before.Sub[i], ctx) + case "value": + val := *evalValue(before.Sub[i].Sub[0], ctx) + if i == len(before.Sub) - 1 && equateType(val.Type, tBool) { + cond = before.Sub[i].Sub[0] + } + } + } + } + + for ; evalValue(cond, ctx).Data.(bool) ; { + fmt.Println("Looping!") + for i := 0; i < len(v.Sub); i++ { + switch v.Sub[i].Data.Data { + case "define": + evalDef(v.Sub[i], ctx) + case "value": + evalValue(v.Sub[i].Sub[0], ctx) + case "block": + ret, val, brk := evalCF(v.Sub[i], ctx) + if ret { + return ret, val, 0 + } else if brk < 0 { + if brk < -1 { + return false, null, brk + 1 + } + goto CONCF + } else if brk > 0 { + return false, null, brk - 1 + } + case "return": + if len(v.Sub[i].Sub) > 0 { + return true, *evalValue(v.Sub[i].Sub[0], ctx), 0 + } + return true, null, 0 + case "break": + brk := 1 + if len(v.Sub[i].Sub) > 0 { + brk = getIntLiteral(v.Sub[i].Sub[0]) + } + if !loop { + return false, null, brk + } + return false, null, brk - 1 + case "continue": + cont := 1 + if len(v.Sub[i].Sub) > 0 { + cont = getIntLiteral(v.Sub[i].Sub[0]) + } + if !loop { + return false, null, -cont + } else if cont == 1 { + goto CONCF + } + return false, null, 1 - cont + } + } + + CONCF: + + if after != nil { + for i := 0; i < len(after.Sub); i++ { + switch after.Sub[i].Data.Data { + case "define": + evalDef(after.Sub[i], ctx) + case "value": + val := *evalValue(after.Sub[i].Sub[0], ctx) + if i == len(after.Sub) - 1 && equateType(val.Type, tBool) { + cond = after.Sub[i].Sub[0] + } + } + } + } + + if !loop { + break + } + } + + return false, null, 0 } -func evalParams(pd tparse.Node, params *[]TVariable, ctx *VarMap) { +func evalParams(pd tparse.Node, params *[]TVariable, ctx *VarMap, method bool) { if len(pd.Sub) == 0 { return } cvt := getType(pd.Sub[0]) pi := 0 + + if method { + (*ctx)["self"] = &(*params)[0] + pi = 1 + } + for i := 1; i < len(pd.Sub); i++ { if pd.Sub[i].Data.Type == 10 && pd.Sub[i].Data.Data == "type" { cvt = getType(pd.Sub[i]) @@ -856,7 +971,7 @@ func evalParams(pd tparse.Node, params *[]TVariable, ctx *VarMap) { } } -func evalBlock(b tparse.Node, params []TVariable) TVariable { +func evalBlock(b tparse.Node, params []TVariable, method bool) TVariable { ctx := make(VarMap) var rty TType = tNull @@ -866,7 +981,7 @@ func evalBlock(b tparse.Node, params []TVariable) TVariable { if b.Sub[0].Sub[i].Data.Data == "[]" { rty = getType(b.Sub[0].Sub[i]) } else if b.Sub[0].Sub[i].Data.Data == "()" { - evalParams(b.Sub[0].Sub[i], ¶ms, &ctx) + evalParams(b.Sub[0].Sub[i], ¶ms, &ctx, method) } } } @@ -876,22 +991,14 @@ func evalBlock(b tparse.Node, params []TVariable) TVariable { case "define": evalDef(b.Sub[i], &ctx) case "value": - fmt.Println("--- Eval Value ---") - fmt.Println(b.Sub[i].Sub[0]) - fmt.Println(*evalValue(b.Sub[i].Sub[0], &ctx)) - fmt.Println("--- End Value ---") + evalValue(b.Sub[i].Sub[0], &ctx) case "block": - ret, val := evalCF(b.Sub[i].Sub[0], &ctx) + ret, val, _ := evalCF(b.Sub[i], &ctx) if ret { return *convertVal(&val, rty) } case "return": - fmt.Println("--- Block return ---") - fmt.Println(b.Sub[i].Sub[0].Sub[0]) - ret := *evalValue(b.Sub[i].Sub[0].Sub[0], &ctx) - fmt.Println(ret) - fmt.Println("--- Return end ---") - return *convertVal(&ret, rty) + return *convertVal(evalValue(b.Sub[i].Sub[0], &ctx), rty) } } @@ -927,5 +1034,5 @@ func EvalTNSL(root *TModule, args string) TVariable { fmt.Println(mainNode) - return evalBlock(*mainNode, []TVariable{targ}) + return evalBlock(*mainNode, []TVariable{targ}, false) } diff --git a/src/tparse/tree-statement.go b/src/tparse/tree-statement.go index b4f891b..c88b102 100644 --- a/src/tparse/tree-statement.go +++ b/src/tparse/tree-statement.go @@ -241,9 +241,10 @@ func keywordStatement(tokens *[]Token, tok, max int) (Node, int) { tok++ // Check for a numerical value and dip case "return": - if (*tokens)[tok].Type != DELIMIT || (*tokens)[tok].Data == "{" || (*tokens)[tok].Data == "(" { - tmp, tok = parseValueList(tokens, tok, max) + if (*tokens)[tok].Type == LINESEP || (*tokens)[tok].Data == ";/" { + return out, tok } + tmp, tok = parseValue(tokens, tok, max) case "alloc", "salloc", "realloc": // Parse value list tmp, tok = parseValueList(tokens, tok, max) -- cgit v1.2.3