From a6c99fcfa6ad54f37bca5b197da14409724b0eb8 Mon Sep 17 00:00:00 2001 From: Ed94 Date: Sun, 24 Jul 2022 09:50:38 -0400 Subject: [PATCH] EOI : lecture 12 compelte --- App/EoI/Scripts/Eva.gd | 45 ++++++++++++++++++++++- App/EoI/Scripts/Lexer.gd | 30 ++++++++------- App/EoI/Scripts/Parser.gd | 77 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 131 insertions(+), 21 deletions(-) diff --git a/App/EoI/Scripts/Eva.gd b/App/EoI/Scripts/Eva.gd index 9e381bb..67efb97 100644 --- a/App/EoI/Scripts/Eva.gd +++ b/App/EoI/Scripts/Eva.gd @@ -46,6 +46,9 @@ func eval( ast ): var result = eval( ast.arg(index) ) if result != null: + if typeof(result) == TYPE_OBJECT && result.get_class() == "ASTNode": + return JSON.print(result.to_SExpression()) + return String( result ) else: return null @@ -83,6 +86,37 @@ func eval( ast ): Env.define(symbol, fnDef) return Env.lookup(symbol) + + NType.fn_Lambda: + var fnDef = \ + [ + ast.arg(1), # Parameters + ast.arg(2), # Body + self # Closure (Environment capture) + ] + + return fnDef + + NType.fn_IIL: + var params = ast.arg(1).arg(1) + var body = ast.arg(1).arg(2) + var fnEva = get_script().new( self, EvalOut ) + + if params.type() != NType.empty: + var index = 1 + while index <= params.num_args(): + var paramVal = eval( ast.arg(index + 1) ) + fnEva.Env.define(params.arg(index), paramVal ) + index += 1 + + var result + + var index = 1; + while index <= body.num_args() : + result = fnEva.eval( body.arg( index ) ) + index += 1 + + return result NType.identifier : return eval_Lookup( ast ) @@ -164,7 +198,7 @@ func eval_Func( ast ): var params = fn[0] var body = fn[1] var fnEva = get_script().new( fn[2], EvalOut ) - + if params.type() != NType.empty: var index = 1 while index <= params.num_args(): @@ -172,7 +206,14 @@ func eval_Func( ast ): fnEva.Env.define(params.arg(index), paramVal ) index += 1 - return fnEva.eval( body ) + var result + + var index = 1; + while index <= body.num_args() : + result = fnEva.eval( body.arg( index ) ) + index += 1 + + return result func eval_Numeric( ast ): if ast.type() == NType.op_Add: diff --git a/App/EoI/Scripts/Lexer.gd b/App/EoI/Scripts/Lexer.gd index a5e9a8c..54f0601 100644 --- a/App/EoI/Scripts/Lexer.gd +++ b/App/EoI/Scripts/Lexer.gd @@ -24,13 +24,14 @@ const TType : Dictionary = \ cmt_SL = "Comment Single-Line", cmt_ML = "Comment Multi-Line", - def_Start = "Expression Start", - def_End = "Expression End", - def_Block = "Expression Block Start", - def_Cond = "Expression Conditional", - def_While = "Expression While", - def_Var = "Variable Declaration", - def_Func = "Function Declaration", + def_Start = "Expression Start", + def_End = "Expression End", + def_Block = "Expression Block Start", + def_Cond = "Expression Conditional", + def_While = "Expression While", + def_Var = "Variable Declaration", + def_Func = "Function Declaration", + def_Lambda = "Lambda Declaration", literal_Number = "Literal: Number", literal_String = "Literal: String", @@ -51,13 +52,14 @@ const Spec : Dictionary = \ TType.fmt_S : "start whitespace.repeat(1-).lazy", - TType.def_Start : "start \\(", - TType.def_End : "start \\)", - TType.def_Block : "start \"begin\"", - TType.def_Cond : "start \"if\"", - TType.def_While : "start \"while\"", - TType.def_Var : "start \"var\"", - TType.def_Func : "start \"def\"", + TType.def_Start : "start \\(", + TType.def_End : "start \\)", + TType.def_Block : "start \"begin\"", + TType.def_Cond : "start \"if\"", + TType.def_While : "start \"while\"", + TType.def_Var : "start \"var\"", + TType.def_Func : "start \"def\"", + TType.def_Lambda : "start \"lambda\"", TType.literal_Number : \ """start diff --git a/App/EoI/Scripts/Parser.gd b/App/EoI/Scripts/Parser.gd index 25a6208..860101f 100644 --- a/App/EoI/Scripts/Parser.gd +++ b/App/EoI/Scripts/Parser.gd @@ -44,9 +44,12 @@ const NType = \ op_Lesser = "<", op_LesserEqual = "<=", - fn_Print = "Print", - fn_User = "User Function", + fn_Print = "Print", + fn_User = "User Function", + fn_Lambda = "Lambda Function", + fn_IIL = "Lambda Function Immediate Invocation", fn_Params = "Function Parameters", + fn_Body = "Function Body", identifier = "Identifier", variable = "Variable" @@ -55,6 +58,10 @@ const NType = \ class ASTNode: var Data : Array + func get_class() : + return "ASTNode" + + func add_Expr( expr ): Data.append(expr) @@ -99,8 +106,11 @@ class ASTNode: result.append( array_Serialize( entry, fn_objSerializer )) elif typeof(entry) == TYPE_OBJECT : - fn_objSerializer.set_instance(entry) - result.append( fn_objSerializer.call_func() ) + if entry.get_class() == "Eva": + result.append(entry) + else: + fn_objSerializer.set_instance(entry) + result.append( fn_objSerializer.call_func() ) else : result.append( entry ) @@ -151,7 +161,7 @@ func parse(): node.add_Expr( parse_Identifier() ) elif NextToken.is_Literal(): - node.Add_Expr( parse_Literal() ) + node.add_Expr( parse_Literal() ) return node @@ -170,6 +180,8 @@ func parse_Expression(): node = parse_Variable() TType.def_Func: node = parse_fn_User() + TType.def_Lambda: + node = parse_fn_Lambda() TType.fn_Print: node = parse_fn_Print() TType.op_Assgin: @@ -180,6 +192,8 @@ func parse_Expression(): node = parse_op_Relational() TType.identifier: node = parse_op_Fn() + TType.def_Start: + node = parse_fn_IIL() var arg = 1 while NextToken.Type != TType.def_End: @@ -267,10 +281,63 @@ func parse_fn_User(): eat(TType.def_End) + var \ + bNode = ASTNode.new() + bNode.set_Type(NType.fn_Body) + + while NextToken.Type != TType.def_End: + bNode.add_Expr( parse_Expression() ) + node.add_Expr( pNode ) + node.add_Expr( bNode ) + + return node + +func parse_fn_Lambda(): + var \ + node = ASTNode.new() + node.set_Type(NType.fn_Lambda) + eat(TType.def_Lambda) + + # Parameters + var \ + pNode = ASTNode.new() + pNode.set_Type(NType.fn_Params) + eat(TType.def_Start) + + while NextToken.Type != TType.def_End: + check( NextToken.Type == TType.identifier, + String("Parser - parse_op_Assign: NextToken should have been identifier, Type: {type} Value: {value}") \ + .format({"type" : NextToken.Type, "value" : NextToken.Value }) + ) + + pNode.add_TokenValue(NextToken) + eat(TType.identifier) + + eat(TType.def_End) + + var \ + bNode = ASTNode.new() + bNode.set_Type(NType.fn_Body) + + while NextToken.Type != TType.def_End: + bNode.add_Expr( parse_Expression() ) + + node.add_Expr( pNode ) + node.add_Expr( bNode ) return node +func parse_fn_IIL(): + var \ + node = ASTNode.new() + node.set_Type(NType.fn_IIL) + + # Lambda + node.add_Expr( parse_Expression() ) + + return node + func parse_Identifier(): var \ node = ASTNode.new()