mirror of
https://github.com/Ed94/LangStudies.git
synced 2025-01-22 04:23:45 -08:00
EOI: Lecture 10 & 11 complete.
This commit is contained in:
parent
ba53395fc7
commit
bd6e39ecdd
@ -42,17 +42,27 @@ margin_bottom = -2.0
|
||||
|
||||
[node name="Eva_Interpret_Btn" type="Button" parent="VBox"]
|
||||
margin_right = 203.0
|
||||
margin_bottom = 30.0
|
||||
margin_bottom = 27.0
|
||||
rect_pivot_offset = Vector2( -123, -302 )
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 0.08
|
||||
theme = ExtResource( 1 )
|
||||
text = "Eva: Interpret"
|
||||
|
||||
[node name="ClearOutput_Btn" type="Button" parent="VBox"]
|
||||
margin_top = 34.0
|
||||
[node name="Eva_ResetEnv_Btn" type="Button" parent="VBox"]
|
||||
margin_top = 31.0
|
||||
margin_right = 203.0
|
||||
margin_bottom = 64.0
|
||||
margin_bottom = 59.0
|
||||
rect_pivot_offset = Vector2( -123, -302 )
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 0.08
|
||||
theme = ExtResource( 1 )
|
||||
text = "Eva: Reset Enviornment"
|
||||
|
||||
[node name="ClearOutput_Btn" type="Button" parent="VBox"]
|
||||
margin_top = 63.0
|
||||
margin_right = 203.0
|
||||
margin_bottom = 91.0
|
||||
rect_pivot_offset = Vector2( -123, -302 )
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 0.08
|
||||
@ -61,14 +71,14 @@ text = "Clear Output"
|
||||
|
||||
[node name="Separator" type="HSeparator" parent="VBox"]
|
||||
modulate = Color( 0.145098, 0.145098, 0.164706, 0 )
|
||||
margin_top = 68.0
|
||||
margin_top = 95.0
|
||||
margin_right = 203.0
|
||||
margin_bottom = 443.0
|
||||
margin_bottom = 445.0
|
||||
size_flags_vertical = 15
|
||||
theme = ExtResource( 5 )
|
||||
|
||||
[node name="Back_Btn" type="Button" parent="VBox"]
|
||||
margin_top = 447.0
|
||||
margin_top = 449.0
|
||||
margin_right = 203.0
|
||||
margin_bottom = 478.0
|
||||
rect_pivot_offset = Vector2( -123, -302 )
|
||||
|
@ -13,18 +13,18 @@ var Eva : SEva
|
||||
|
||||
|
||||
# UX --------------------------------------------------------
|
||||
onready var Editor = get_node("Editor_TEdit")
|
||||
onready var Output = get_node("Output_TEdit")
|
||||
onready var Debug = get_node("Debug_TEdit")
|
||||
onready var Eva_Btn = get_node("VBox/Eva_Interpret_Btn")
|
||||
onready var Clear_Btn = get_node("VBox/ClearOutput_Btn")
|
||||
onready var Back_Btn = get_node("VBox/Back_Btn")
|
||||
onready var Editor = get_node("Editor_TEdit")
|
||||
onready var Output = get_node("Output_TEdit")
|
||||
onready var Debug = get_node("Debug_TEdit")
|
||||
onready var Eva_Btn = get_node("VBox/Eva_Interpret_Btn")
|
||||
onready var Eva_Reset_Btn = get_node("VBox/Eva_ResetEnv_Btn")
|
||||
onready var Clear_Btn = get_node("VBox/ClearOutput_Btn")
|
||||
onready var Back_Btn = get_node("VBox/Back_Btn")
|
||||
|
||||
|
||||
func evaBtn_pressed():
|
||||
Lexer = SLexer.new(Editor.text, Output)
|
||||
Parser = SParser.new(Lexer, Output)
|
||||
Eva = SEva.new(null, Output)
|
||||
|
||||
var ast = Parser.parse()
|
||||
var result = Eva.eval(ast)
|
||||
@ -34,6 +34,10 @@ func evaBtn_pressed():
|
||||
|
||||
Debug.text = JSON.print( Eva.get_EnvSnapshot(), "\t" )
|
||||
|
||||
func evaResetBtn_pressed():
|
||||
Eva = SEva.new(null, Output)
|
||||
Debug.text = JSON.print( Eva.get_EnvSnapshot(), "\t" )
|
||||
|
||||
func clearBtn_pressed():
|
||||
Output.text = ""
|
||||
|
||||
@ -42,6 +46,10 @@ func backBtn_pressed():
|
||||
|
||||
|
||||
func _ready():
|
||||
Eva = SEva.new(null, Output)
|
||||
Debug.text = JSON.print( Eva.get_EnvSnapshot(), "\t" )
|
||||
|
||||
Eva_Btn.connect("pressed", self, "evaBtn_pressed")
|
||||
Eva_Reset_Btn.connect("pressed", self, "evaResetBtn_pressed")
|
||||
Clear_Btn.connect("pressed", self, "clearBtn_pressed")
|
||||
Back_Btn.connect("pressed", self, "backBtn_pressed")
|
||||
|
@ -25,11 +25,17 @@ var Env : EvaEnv
|
||||
var Parent
|
||||
# ---------------------------------------------------------- GLOBALS END
|
||||
|
||||
func get_class():
|
||||
return "Eva"
|
||||
|
||||
func _init(parent, evalOut):
|
||||
EvalOut = evalOut
|
||||
Env = EvaEnv.new(EvalOut)
|
||||
Parent = parent
|
||||
|
||||
if Parent == null:
|
||||
Env.setup_Globals()
|
||||
|
||||
func eval( ast ):
|
||||
match ast.type():
|
||||
NType.program :
|
||||
@ -47,7 +53,7 @@ func eval( ast ):
|
||||
NType.block :
|
||||
return eval_Block( ast )
|
||||
|
||||
NType.conditional:
|
||||
NType.conditional :
|
||||
var condition = eval( ast.arg(1) )
|
||||
|
||||
if condition:
|
||||
@ -58,7 +64,7 @@ func eval( ast ):
|
||||
if ast.num_args() > 2:
|
||||
return eval( ast.arg(3))
|
||||
|
||||
NType.expr_While:
|
||||
NType.expr_While :
|
||||
var result
|
||||
|
||||
while eval( ast.arg(1) ):
|
||||
@ -66,32 +72,33 @@ func eval( ast ):
|
||||
|
||||
return result
|
||||
|
||||
NType.fn_User :
|
||||
var symbol = ast.arg(1)
|
||||
var fnDef = \
|
||||
[
|
||||
ast.arg(2), # Parameters
|
||||
ast.arg(3), # Body
|
||||
self # Closure (Environment capture)
|
||||
]
|
||||
|
||||
Env.define(symbol, fnDef)
|
||||
return Env.lookup(symbol)
|
||||
|
||||
NType.identifier :
|
||||
var identifier = ast.arg(1)
|
||||
|
||||
if Parent != null && !Env.has( identifier):
|
||||
return Parent.Env.lookup( identifier )
|
||||
|
||||
return Env.lookup( identifier )
|
||||
return eval_Lookup( ast )
|
||||
|
||||
NType.op_Assign :
|
||||
var symbol = ast.arg(1)
|
||||
var value = eval( ast.arg(2) )
|
||||
return eval_Assign( ast )
|
||||
|
||||
if Parent != null && !Env.has( symbol):
|
||||
return Parent.Env.set( symbol, value )
|
||||
|
||||
return Env.set( symbol, value )
|
||||
NType.op_Fn:
|
||||
return eval_Func( ast )
|
||||
|
||||
NType.op_Greater:
|
||||
return eval( ast.arg(1) ) > eval( ast.arg(2) )
|
||||
|
||||
NType.op_Lesser:
|
||||
return eval( ast.arg(1) ) < eval( ast.arg(2) )
|
||||
|
||||
NType.op_GreaterEqual:
|
||||
return eval( ast.arg(1) ) >= eval( ast.arg(2) )
|
||||
|
||||
NType.op_LesserEqual:
|
||||
return eval( ast.arg(1) ) <= eval( ast.arg(2) )
|
||||
|
||||
@ -100,10 +107,14 @@ func eval( ast ):
|
||||
|
||||
NType.variable :
|
||||
var symbol = ast.arg(1)
|
||||
var value = eval( ast.arg(2) )
|
||||
var value
|
||||
|
||||
Env.define_Var(symbol, value)
|
||||
return value
|
||||
if ast.num_args() == 2:
|
||||
value = eval( ast.arg(2) )
|
||||
|
||||
Env.define(symbol, value)
|
||||
|
||||
return Env.lookup(symbol)
|
||||
|
||||
if ast.is_Number() :
|
||||
return float( ast.arg(1) )
|
||||
@ -125,6 +136,44 @@ func eval_Block( ast ):
|
||||
|
||||
return result
|
||||
|
||||
func eval_Lookup( ast ) :
|
||||
var identifier = ast.arg(1)
|
||||
|
||||
if Parent != null && !Env.has( identifier):
|
||||
return Parent.eval_Lookup( ast )
|
||||
|
||||
return Env.lookup( identifier )
|
||||
|
||||
func eval_Assign( ast, oriEva = null ) :
|
||||
var symbol = ast.arg(1)
|
||||
|
||||
if Parent != null && !Env.has( symbol):
|
||||
return Parent.eval_Assign( ast, self )
|
||||
|
||||
var value
|
||||
|
||||
if oriEva != null :
|
||||
value = oriEva.eval( ast.arg(2) )
|
||||
else :
|
||||
value = eval( ast.arg(2) )
|
||||
|
||||
return Env.set( symbol, value )
|
||||
|
||||
func eval_Func( ast ):
|
||||
var fn = eval_Lookup( 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():
|
||||
var paramVal = eval( ast.arg(index + 1) )
|
||||
fnEva.Env.define(params.arg(index), paramVal )
|
||||
index += 1
|
||||
|
||||
return fnEva.eval( body )
|
||||
|
||||
func eval_Numeric( ast ):
|
||||
if ast.type() == NType.op_Add:
|
||||
var result = 0.0; var index = 1
|
||||
@ -136,6 +185,9 @@ func eval_Numeric( ast ):
|
||||
return result
|
||||
|
||||
if ast.type() == NType.op_Sub:
|
||||
if ast.num_args() == 2:
|
||||
return -eval( ast.arg(1) )
|
||||
|
||||
var result = 0.0; var index = 1
|
||||
|
||||
while index <= ast.num_args():
|
||||
@ -171,9 +223,11 @@ func eval_Print( ast ):
|
||||
return null
|
||||
|
||||
func get_EnvSnapshot():
|
||||
var snapshot = Env.Records.duplicate(true)
|
||||
var \
|
||||
snapshot = EvaEnv.new(EvalOut)
|
||||
snapshot.Records = Env.Records.duplicate(true)
|
||||
|
||||
if Parent != null:
|
||||
snapshot[Parent] = Parent.Env.Records.duplicate(true)
|
||||
snapshot[Parent] = Parent.get_EnvSnapshot()
|
||||
|
||||
return snapshot
|
||||
return snapshot.to_Dictionary()
|
||||
|
@ -19,15 +19,17 @@ class_name EvaEnv
|
||||
var Records : Dictionary
|
||||
|
||||
|
||||
func _init(errorOut):
|
||||
ErrorOut = errorOut
|
||||
|
||||
func define_Var(symbol : String, value) :
|
||||
func define(symbol : String, value) :
|
||||
Records[symbol] = value
|
||||
|
||||
func has(symbol : String) :
|
||||
return Records.has(symbol)
|
||||
|
||||
func lookup(symbol : String) :
|
||||
check(Records.has(symbol), String("Symbol not found in environment records"))
|
||||
|
||||
return Records[symbol]
|
||||
|
||||
func set(symbol : String, value) :
|
||||
check(Records.has(symbol), String("Symbol not found in environment records"))
|
||||
|
||||
@ -35,7 +37,83 @@ func set(symbol : String, value) :
|
||||
|
||||
return Records[symbol]
|
||||
|
||||
func lookup(symbol : String) :
|
||||
check(Records.has(symbol), String("Symbol not found in environment records"))
|
||||
func setup_Globals():
|
||||
Records["null"] = null
|
||||
Records["true"] = true
|
||||
Records["false"] = false
|
||||
|
||||
return Records[symbol]
|
||||
|
||||
func _init(errorOut):
|
||||
ErrorOut = errorOut
|
||||
|
||||
|
||||
# Serialization ----------------------------------------------------
|
||||
var SEva
|
||||
|
||||
func array_Serialize(array, fn_objSerializer) :
|
||||
var result = []
|
||||
|
||||
for entry in array :
|
||||
if typeof(entry) == TYPE_ARRAY :
|
||||
result.append( array_Serialize( entry, fn_objSerializer ))
|
||||
|
||||
elif typeof(entry) == TYPE_OBJECT :
|
||||
if entry.get_class() == "Eva":
|
||||
result.append(entry)
|
||||
else:
|
||||
fn_objSerializer.set_instance(entry)
|
||||
result.append( fn_objSerializer.call_func() )
|
||||
else :
|
||||
result.append( entry )
|
||||
|
||||
return result
|
||||
|
||||
func to_SExpression():
|
||||
var expression = []
|
||||
|
||||
for key in Records.keys() :
|
||||
var entry = [key]
|
||||
var Value = Records[key]
|
||||
|
||||
if typeof( Value ) == TYPE_ARRAY :
|
||||
var \
|
||||
to_SExpression_Fn = FuncRef.new()
|
||||
to_SExpression_Fn.set_function("to_SExpression")
|
||||
|
||||
var array = array_Serialize( Value, to_SExpression_Fn )
|
||||
|
||||
entry.append(array)
|
||||
|
||||
elif typeof( Value ) == TYPE_OBJECT :
|
||||
entry.append( Value.to_SExpression() )
|
||||
|
||||
else :
|
||||
entry.append(Value)
|
||||
|
||||
expression.append(entry)
|
||||
|
||||
return expression
|
||||
|
||||
func to_Dictionary():
|
||||
var result = {}
|
||||
|
||||
for key in Records.keys() :
|
||||
var Value = Records[key]
|
||||
|
||||
if typeof(Value) == TYPE_ARRAY :
|
||||
var \
|
||||
to_SExpression_Fn = FuncRef.new()
|
||||
to_SExpression_Fn.set_function("to_SExpression")
|
||||
|
||||
var array = array_Serialize( Value, to_SExpression_Fn )
|
||||
|
||||
result[key] = array
|
||||
|
||||
elif typeof(Value) == TYPE_OBJECT :
|
||||
result[key] = Value.to_SExpression()
|
||||
|
||||
else :
|
||||
result[key] = Value
|
||||
|
||||
return result
|
||||
# Serialization END -------------------------------------------------
|
||||
|
@ -24,12 +24,13 @@ const TType : Dictionary = \
|
||||
cmt_SL = "Comment Single-Line",
|
||||
cmt_ML = "Comment Multi-Line",
|
||||
|
||||
def_Block = "Expression Block Start",
|
||||
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",
|
||||
|
||||
literal_Number = "Literal: Number",
|
||||
literal_String = "Literal: String",
|
||||
@ -50,12 +51,13 @@ const Spec : Dictionary = \
|
||||
|
||||
TType.fmt_S : "start whitespace.repeat(1-).lazy",
|
||||
|
||||
TType.def_Block : "start \"begin\"",
|
||||
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.literal_Number : \
|
||||
"""start
|
||||
|
@ -21,6 +21,8 @@ const NType = \
|
||||
{
|
||||
program = "Program",
|
||||
|
||||
empty = "Empty",
|
||||
|
||||
block = "Scope Block",
|
||||
|
||||
conditional = "Conditional",
|
||||
@ -30,6 +32,7 @@ const NType = \
|
||||
literal_String = "Literal: String",
|
||||
|
||||
op_Assign = "Assignment",
|
||||
op_Fn = "Function Call",
|
||||
|
||||
op_Add = "+",
|
||||
op_Sub = "-",
|
||||
@ -42,9 +45,11 @@ const NType = \
|
||||
op_LesserEqual = "<=",
|
||||
|
||||
fn_Print = "Print",
|
||||
fn_User = "User Function",
|
||||
fn_Params = "Function Parameters",
|
||||
|
||||
identifier = "Identifier",
|
||||
variable = "Variable"
|
||||
variable = "Variable"
|
||||
}
|
||||
|
||||
class ASTNode:
|
||||
@ -163,6 +168,8 @@ func parse_Expression():
|
||||
node = parse_While()
|
||||
TType.def_Var:
|
||||
node = parse_Variable()
|
||||
TType.def_Func:
|
||||
node = parse_fn_User()
|
||||
TType.fn_Print:
|
||||
node = parse_fn_Print()
|
||||
TType.op_Assgin:
|
||||
@ -171,7 +178,8 @@ func parse_Expression():
|
||||
node = parse_op_Numeric()
|
||||
TType.op_Relational:
|
||||
node = parse_op_Relational()
|
||||
|
||||
TType.identifier:
|
||||
node = parse_op_Fn()
|
||||
|
||||
var arg = 1
|
||||
while NextToken.Type != TType.def_End:
|
||||
@ -184,6 +192,10 @@ func parse_Expression():
|
||||
|
||||
eat(TType.def_End)
|
||||
|
||||
if node == null:
|
||||
node = ASTNode.new()
|
||||
node.set_Type(NType.empty)
|
||||
|
||||
return node
|
||||
|
||||
func parse_Block():
|
||||
@ -222,11 +234,40 @@ func parse_Variable():
|
||||
node.add_TokenValue( NextToken )
|
||||
eat(TType.identifier)
|
||||
|
||||
if NextToken.Type == TType.def_Start :
|
||||
node.add_Expr( parse_Expression() )
|
||||
return node
|
||||
|
||||
else :
|
||||
node.add_Expr( parse_Literal() )
|
||||
func parse_fn_User():
|
||||
var \
|
||||
node = ASTNode.new()
|
||||
node.set_Type(NType.fn_User)
|
||||
eat(TType.def_Func)
|
||||
|
||||
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 })
|
||||
)
|
||||
|
||||
node.add_TokenValue( NextToken )
|
||||
eat(TType.identifier)
|
||||
|
||||
# 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)
|
||||
|
||||
node.add_Expr( pNode )
|
||||
|
||||
return node
|
||||
|
||||
@ -306,6 +347,15 @@ func parse_op_Relational():
|
||||
|
||||
return node
|
||||
|
||||
func parse_op_Fn():
|
||||
var \
|
||||
node = ASTNode.new()
|
||||
node.set_Type(NType.op_Fn)
|
||||
node.add_TokenValue( NextToken )
|
||||
eat(TType.identifier)
|
||||
|
||||
return node
|
||||
|
||||
func parse_Literal():
|
||||
var node = ASTNode.new()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user