LangStudies/App/EoI/Scripts/Eva.gd

148 lines
3.2 KiB
GDScript3
Raw Normal View History

2022-07-20 06:27:19 -07:00
extends Object
2022-07-23 23:56:37 -07:00
# ---------------------------------------------------------- UTILITIES
var EvalOut
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
func check( condition : bool, message : String):
assert(condition, message)
if ! condition:
EvalOut.text = "Eva - Error: " + message
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
func throw( message ):
assert(false, message)
EvalOut.text = "Eva - Error: " + message
# ---------------------------------------------------------- UTILITIES END
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
class_name Eva
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
# ---------------------------------------------------------- GLOBALS
const Parser = preload("Parser.gd")
const NType = Parser.NType
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
const EvaEnv = preload("EvaEnv.gd")
var Env : EvaEnv
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
var Parent
# ---------------------------------------------------------- GLOBALS END
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
func _init(parent, evalOut):
EvalOut = evalOut
Env = EvaEnv.new(EvalOut)
Parent = parent
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
func eval( ast ):
if ast.type() == NType.program :
var index = 1;
while index < ast.num_args():
eval( ast.arg(index) )
index += 1
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
var result = eval( ast.arg(index) )
if result != null:
return String( result )
else:
return null
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
elif ast.type() == NType.block :
return eval_Block( ast )
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
elif ast.type() == NType.identifier :
var identifier = ast.arg(1)
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
if Parent != null && !Env.has( identifier):
return Parent.Env.lookup( identifier )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
return Env.lookup( identifier )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
elif ast.type() == NType.fn_Print :
return eval_Print( ast )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
elif ast.type() == NType.op_Assign :
var symbol = ast.arg(1)
var value = eval( ast.arg(2) )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
if Parent != null && !Env.has( symbol):
return Parent.Env.set( symbol, value )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
return Env.set( symbol, value )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
elif ast.type() == NType.variable :
var symbol = ast.arg(1)
var value = eval( ast.arg(2) )
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
Env.define_Var(symbol, value)
return value
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
elif ast.is_Number() :
return float( ast.arg(1) )
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
elif ast.is_String() :
return ast.string()
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
return eval_Numeric( ast )
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
var msgT = "eval - Unimplemented: {ast}"
var msg = msgT.format({"ast" : JSON.print(ast.to_SExpression(), "\t") })
throw(msg)
2022-07-20 06:27:19 -07:00
2022-07-23 23:56:37 -07:00
func eval_Block( ast ):
var eva_Block = get_script().new( self, EvalOut )
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
var result
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
var index = 1;
while index <= ast.num_args() :
result = eva_Block.eval( ast.arg(index) )
index += 1
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
return result
2022-07-20 11:57:26 -07:00
func eval_Numeric( ast ):
2022-07-20 06:27:19 -07:00
if ast.type() == NType.op_Add:
2022-07-20 11:57:26 -07:00
var result = 0.0; var index = 1
while index <= ast.num_args():
2022-07-23 23:56:37 -07:00
result += eval( ast.arg(index) )
2022-07-20 11:57:26 -07:00
index += 1
return result
if ast.type() == NType.op_Sub:
var result = 0.0; var index = 1
while index <= ast.num_args():
2022-07-23 23:56:37 -07:00
result -= eval( ast.arg(index) )
2022-07-20 11:57:26 -07:00
index += 1
return result
2022-07-20 06:27:19 -07:00
if ast.type() == NType.op_Mult:
2022-07-20 11:57:26 -07:00
var result = 1.0; var index = 1
while index <= ast.num_args():
2022-07-23 23:56:37 -07:00
result *= eval( ast.arg(index) )
2022-07-20 11:57:26 -07:00
index += 1
return result
if ast.type() == NType.op_Div:
var result = 1.0; var index = 1
while index <= ast.num_args():
2022-07-23 23:56:37 -07:00
result /= eval( ast.arg(index) )
2022-07-20 11:57:26 -07:00
result += 1
return result
2022-07-23 23:56:37 -07:00
func eval_Print( ast ):
EvalOut.text += "\n" + String( eval( ast.arg(1) ) )
return null
2022-07-20 11:57:26 -07:00
2022-07-23 23:56:37 -07:00
func get_EnvSnapshot():
var snapshot = Env.Records.duplicate(true)
if Parent != null:
snapshot[Parent] = Parent.Env.Records.duplicate(true)
return snapshot