fully cleaned up the compiler
This commit is contained in:
parent
13d2391e57
commit
83c4808d5a
|
@ -83,7 +83,6 @@ func _on_dialogue_finished():
|
||||||
|
|
||||||
func _on_node_start(node):
|
func _on_node_start(node):
|
||||||
emit_signal('node_started', node)
|
emit_signal('node_started', node)
|
||||||
resume()
|
|
||||||
|
|
||||||
func _on_node_finished(node):
|
func _on_node_finished(node):
|
||||||
emit_signal('node_finished', node)
|
emit_signal('node_finished', node)
|
||||||
|
|
|
@ -8,21 +8,15 @@ const Parser = preload('res://addons/Wol/core/compiler/parser.gd')
|
||||||
|
|
||||||
const INVALID_TITLE = '[\\[<>\\]{}\\|:\\s#\\$]'
|
const INVALID_TITLE = '[\\[<>\\]{}\\|:\\s#\\$]'
|
||||||
|
|
||||||
const NO_ERROR = 0x00
|
|
||||||
const LEXER_FAILURE = 0x01
|
|
||||||
const PARSER_FAILURE = 0x02
|
|
||||||
const INVALID_HEADER = 0x04
|
|
||||||
const ERR_COMPILATION_FAILED = 0x10
|
|
||||||
|
|
||||||
var source = ''
|
var source = ''
|
||||||
var filename = ''
|
var filename = ''
|
||||||
|
|
||||||
var _current_node
|
var current_node
|
||||||
var _contains_implicit_string_tags = false
|
var has_implicit_string_tags = false
|
||||||
var _label_count = 0
|
|
||||||
|
|
||||||
var _string_table = {}
|
var string_count = 0
|
||||||
var _string_count = 0
|
var string_table = {}
|
||||||
|
var label_count = 0
|
||||||
|
|
||||||
func _init(_filename, _source = null):
|
func _init(_filename, _source = null):
|
||||||
filename = _filename
|
filename = _filename
|
||||||
|
@ -50,7 +44,6 @@ func compile():
|
||||||
source_lines[i] = source_lines[i].strip_edges(false, true)
|
source_lines[i] = source_lines[i].strip_edges(false, true)
|
||||||
|
|
||||||
var parsed_nodes = []
|
var parsed_nodes = []
|
||||||
|
|
||||||
while line_number < source_lines.size():
|
while line_number < source_lines.size():
|
||||||
var title = ''
|
var title = ''
|
||||||
var body = ''
|
var body = ''
|
||||||
|
@ -77,8 +70,6 @@ func compile():
|
||||||
if line_number >= source_lines.size() or line == '---':
|
if line_number >= source_lines.size() or line == '---':
|
||||||
break
|
break
|
||||||
|
|
||||||
line_number += 1
|
|
||||||
|
|
||||||
# past header
|
# past header
|
||||||
var body_lines = []
|
var body_lines = []
|
||||||
|
|
||||||
|
@ -108,8 +99,8 @@ func compile():
|
||||||
for node in parsed_nodes:
|
for node in parsed_nodes:
|
||||||
compile_node(program, node)
|
compile_node(program, node)
|
||||||
|
|
||||||
for key in _string_table:
|
for key in string_table:
|
||||||
program.strings[key] = _string_table[key]
|
program.strings[key] = string_table[key]
|
||||||
|
|
||||||
return program
|
return program
|
||||||
|
|
||||||
|
@ -131,7 +122,7 @@ func compile_node(program, parsed_node):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
var start_label = register_label()
|
var start_label = register_label()
|
||||||
emit(Constants.ByteCode.Label,node_compiled,[Program.Operand.new(start_label)])
|
emit(Constants.ByteCode.Label, node_compiled, [Program.Operand.new(start_label)])
|
||||||
|
|
||||||
for statement in parsed_node.statements:
|
for statement in parsed_node.statements:
|
||||||
generate_statement(node_compiled, statement)
|
generate_statement(node_compiled, statement)
|
||||||
|
@ -151,110 +142,102 @@ func compile_node(program, parsed_node):
|
||||||
|
|
||||||
program.nodes[node_compiled.name] = node_compiled
|
program.nodes[node_compiled.name] = node_compiled
|
||||||
|
|
||||||
func register_string(text:String,node_name:String,id:String='',line_number:int=-1,tags:Array=[])->String:
|
func register_string(text, node_name, id = '', line_number = -1, tags = []):
|
||||||
var line_id_used : String
|
var line_id_used = ''
|
||||||
|
var implicit = false
|
||||||
var implicit : bool
|
|
||||||
|
|
||||||
if id.empty():
|
if id.empty():
|
||||||
line_id_used = '%s-%s-%d' % [self.filename,node_name,self._string_count]
|
line_id_used = '%s-%s-%d' % [filename, node_name, string_count]
|
||||||
self._string_count+=1
|
string_count += 1
|
||||||
|
|
||||||
#use this when we generate implicit tags
|
#use this when we generate implicit tags
|
||||||
#they are not saved and are generated
|
#they are not saved and are generated
|
||||||
#aka dummy tags that change on each compilation
|
#aka dummy tags that change on each compilation
|
||||||
_contains_implicit_string_tags = true
|
has_implicit_string_tags = true
|
||||||
|
|
||||||
implicit = true
|
implicit = true
|
||||||
else :
|
else :
|
||||||
line_id_used = id
|
line_id_used = id
|
||||||
implicit = false
|
implicit = false
|
||||||
|
|
||||||
var string_info = Program.Line.new(text,node_name,line_number,filename,implicit,tags)
|
var string_info = Program.Line.new(text, node_name, line_number, filename, implicit, tags)
|
||||||
#add to string table and return id
|
string_table[line_id_used] = string_info
|
||||||
self._string_table[line_id_used] = string_info
|
|
||||||
|
|
||||||
return line_id_used
|
return line_id_used
|
||||||
|
|
||||||
func register_label(comment:String='')->String:
|
func register_label(comment = ''):
|
||||||
_label_count+=1
|
label_count += 1
|
||||||
return 'L%s%s' %[ _label_count , comment]
|
return 'Label%s%s' % [label_count, comment]
|
||||||
|
|
||||||
func emit(bytecode, node = _current_node, operands = []):
|
func emit(bytecode, node = current_node, operands = []):
|
||||||
var instruction = Program.Instruction.new(null)
|
var instruction = Program.Instruction.new(null)
|
||||||
instruction.operation = bytecode
|
instruction.operation = bytecode
|
||||||
instruction.operands = operands
|
instruction.operands = operands
|
||||||
|
|
||||||
if node == null:
|
if node == null:
|
||||||
printerr('trying to emit to null node with byte_code: %s' % bytecode)
|
printerr('Trying to emit to null node with byte_code: %s' % bytecode)
|
||||||
return
|
return
|
||||||
|
|
||||||
node.instructions.append(instruction)
|
node.instructions.append(instruction)
|
||||||
|
|
||||||
if bytecode == Constants.ByteCode.Label:
|
if bytecode == Constants.ByteCode.Label:
|
||||||
#add to label table
|
node.labels[instruction.operands[0].value] = node.instructions.size() - 1
|
||||||
node.labels[instruction.operands[0].value] = node.instructions.size()-1
|
|
||||||
|
|
||||||
|
|
||||||
func generate_header():
|
|
||||||
pass
|
|
||||||
|
|
||||||
func generate_statement(node,statement):
|
|
||||||
|
|
||||||
|
func generate_statement(node, statement):
|
||||||
match statement.type:
|
match statement.type:
|
||||||
Constants.StatementTypes.CustomCommand:
|
Constants.StatementTypes.CustomCommand:
|
||||||
generate_custom_command(node,statement.custom_command)
|
generate_custom_command(node, statement.custom_command)
|
||||||
|
|
||||||
Constants.StatementTypes.ShortcutOptionGroup:
|
Constants.StatementTypes.ShortcutOptionGroup:
|
||||||
generate_shortcut_group(node,statement.shortcut_option_group)
|
generate_shortcut_group(node, statement.shortcut_option_group)
|
||||||
|
|
||||||
Constants.StatementTypes.Block:
|
Constants.StatementTypes.Block:
|
||||||
generate_block(node,statement.block.statements)
|
generate_block(node, statement.block.statements)
|
||||||
|
|
||||||
Constants.StatementTypes.IfStatement:
|
Constants.StatementTypes.IfStatement:
|
||||||
generate_if(node,statement.if_statement)
|
generate_if(node, statement.if_statement)
|
||||||
|
|
||||||
Constants.StatementTypes.OptionStatement:
|
Constants.StatementTypes.OptionStatement:
|
||||||
generate_option(node,statement.option_statement)
|
generate_option(node, statement.option_statement)
|
||||||
|
|
||||||
Constants.StatementTypes.AssignmentStatement:
|
Constants.StatementTypes.AssignmentStatement:
|
||||||
generate_assignment(node,statement.assignment)
|
generate_assignment(node, statement.assignment)
|
||||||
|
|
||||||
Constants.StatementTypes.Line:
|
Constants.StatementTypes.Line:
|
||||||
generate_line(node,statement,statement.line)
|
generate_line(node, statement,statement.line)
|
||||||
_:
|
_:
|
||||||
assert(false, 'Illegal statement type [%s]. Could not generate code.' % statement.type)
|
assert(false, 'Illegal statement type [%s]. Could not generate code.' % statement.type)
|
||||||
|
|
||||||
#compile instructions for custom commands
|
func generate_custom_command(node, command):
|
||||||
func generate_custom_command(node,command):
|
# TODO: See if the first tree of this statement is being used
|
||||||
#print('generating custom command')
|
|
||||||
#can evaluate command
|
|
||||||
if command.expression != null:
|
if command.expression != null:
|
||||||
generate_expression(node,command.expression)
|
generate_expression(node, command.expression)
|
||||||
else:
|
else:
|
||||||
var command_string = command.client_command
|
var command_string = command.client_command
|
||||||
if command_string == 'stop':
|
if command_string == 'stop':
|
||||||
emit(Constants.ByteCode.Stop,node)
|
emit(Constants.ByteCode.Stop, node)
|
||||||
else :
|
else :
|
||||||
emit(Constants.ByteCode.RunCommand,node,[Program.Operand.new(command_string)])
|
emit(Constants.ByteCode.RunCommand, node, [Program.Operand.new(command_string)])
|
||||||
|
|
||||||
#compile instructions for linetags and use them
|
func generate_line(node, statement, line):
|
||||||
# \#line:number
|
# TODO: Implement proper line numbers (global and local)
|
||||||
func generate_line(node,statement,line:String):
|
var num = register_string(line, node.name, '', statement.line_number, []);
|
||||||
var num : String = register_string(line, node.name, '', statement.line_number, []);
|
|
||||||
emit(Constants.ByteCode.RunLine, node, [Program.Operand.new(num)])
|
emit(Constants.ByteCode.RunLine, node, [Program.Operand.new(num)])
|
||||||
|
|
||||||
func generate_shortcut_group(node,shortcut_group):
|
func generate_shortcut_group(node,shortcut_group):
|
||||||
# print('generating shortcutoptopn group')
|
var end = register_label('group_end')
|
||||||
var end : String = register_label('group_end')
|
var labels = []
|
||||||
|
var option_count = 0
|
||||||
var labels : Array = []#String
|
|
||||||
|
|
||||||
var option_count : int = 0
|
|
||||||
|
|
||||||
for option in shortcut_group.options:
|
for option in shortcut_group.options:
|
||||||
var op_destination : String = register_label('option_%s'%[option_count+1])
|
var endof_clause = ''
|
||||||
|
var op_destination = register_label('option_%s' % [option_count + 1])
|
||||||
|
|
||||||
labels.append(op_destination)
|
labels.append(op_destination)
|
||||||
|
|
||||||
var endof_clause : String = ''
|
if option.condition != null:
|
||||||
|
endof_clause = register_label('conditional_%s' % option_count)
|
||||||
if option.condition != null :
|
generate_expression(node, option.condition)
|
||||||
endof_clause = register_label('conditional_%s'%option_count)
|
|
||||||
generate_expression(node,option.condition)
|
|
||||||
emit(Constants.ByteCode.JumpIfFalse, node, [Program.Operand.new(endof_clause)])
|
emit(Constants.ByteCode.JumpIfFalse, node, [Program.Operand.new(endof_clause)])
|
||||||
|
|
||||||
var label_line_id = '' #TODO: Add tag support
|
var label_line_id = '' #TODO: Add tag support
|
||||||
|
@ -265,168 +248,153 @@ func generate_shortcut_group(node,shortcut_group):
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(label_string_id),Program.Operand.new(op_destination)])
|
emit(Constants.ByteCode.AddOption, node, [Program.Operand.new(label_string_id), Program.Operand.new(op_destination)])
|
||||||
|
|
||||||
if option.condition != null :
|
if option.condition != null:
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(endof_clause)])
|
emit(Constants.ByteCode.Label, node, [Program.Operand.new(endof_clause)])
|
||||||
emit(Constants.ByteCode.Pop,node)
|
emit(Constants.ByteCode.Pop, node)
|
||||||
|
|
||||||
option_count+=1
|
option_count += 1
|
||||||
|
|
||||||
emit(Constants.ByteCode.ShowOptions,node)
|
emit(Constants.ByteCode.ShowOptions, node)
|
||||||
emit(Constants.ByteCode.Jump,node)
|
emit(Constants.ByteCode.Jump, node)
|
||||||
|
|
||||||
option_count = 0
|
option_count = 0
|
||||||
|
|
||||||
for option in shortcut_group.options:
|
for option in shortcut_group.options:
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(labels[option_count])])
|
emit(Constants.ByteCode.Label, node, [Program.Operand.new(labels[option_count])])
|
||||||
|
|
||||||
if option.node != null :
|
if option.node != null:
|
||||||
generate_block(node,option.node.statements)
|
generate_block(node, option.node.statements)
|
||||||
emit(Constants.ByteCode.JumpTo,node,[Program.Operand.new(end)])
|
emit(Constants.ByteCode.JumpTo, node, [Program.Operand.new(end)])
|
||||||
option_count+=1
|
option_count += 1
|
||||||
|
|
||||||
#end of option group
|
emit(Constants.ByteCode.Label, node, [Program.Operand.new(end)])
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(end)])
|
emit(Constants.ByteCode.Pop, node)
|
||||||
#clean up
|
|
||||||
emit(Constants.ByteCode.Pop,node)
|
|
||||||
|
|
||||||
|
func generate_block(node, statements = []):
|
||||||
#compile instructions for block
|
if not statements.empty():
|
||||||
#blocks are just groups of statements
|
|
||||||
func generate_block(node,statements:Array=[]):
|
|
||||||
# print('generating block')
|
|
||||||
if !statements.empty():
|
|
||||||
for statement in statements:
|
for statement in statements:
|
||||||
generate_statement(node,statement)
|
generate_statement(node, statement)
|
||||||
|
|
||||||
|
|
||||||
#compile if branching instructions
|
func generate_if(node, if_statement):
|
||||||
func generate_if(node,if_statement):
|
var endif = register_label('endif')
|
||||||
# print('generating if')
|
|
||||||
#jump to label @ end of every clause
|
|
||||||
var endif : String = register_label('endif')
|
|
||||||
|
|
||||||
for clause in if_statement.clauses:
|
for clause in if_statement.clauses:
|
||||||
var end_clause : String = register_label('skip_clause')
|
var end_clause = register_label('skip_clause')
|
||||||
|
|
||||||
if clause.expression!=null:
|
if clause.expression != null:
|
||||||
generate_expression(node,clause.expression)
|
generate_expression(node, clause.expression)
|
||||||
emit(Constants.ByteCode.JumpIfFalse,node,[Program.Operand.new(end_clause)])
|
emit(Constants.ByteCode.JumpIfFalse, node, [Program.Operand.new(end_clause)])
|
||||||
|
|
||||||
generate_block(node,clause.statements)
|
generate_block(node,clause.statements)
|
||||||
emit(Constants.ByteCode.JumpTo,node,[Program.Operand.new(endif)])
|
emit(Constants.ByteCode.JumpTo, node, [Program.Operand.new(endif)])
|
||||||
|
|
||||||
if clause.expression!=null:
|
if clause.expression != null:
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(end_clause)])
|
emit(Constants.ByteCode.Label, node, [Program.Operand.new(end_clause)])
|
||||||
|
|
||||||
if clause.expression!=null:
|
if clause.expression != null:
|
||||||
emit(Constants.ByteCode.Pop)
|
emit(Constants.ByteCode.Pop)
|
||||||
|
|
||||||
|
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(endif)])
|
emit(Constants.ByteCode.Label, node, [Program.Operand.new(endif)])
|
||||||
|
|
||||||
|
func generate_option(node, option):
|
||||||
#compile instructions for options
|
var destination = option.destination
|
||||||
func generate_option(node,option):
|
|
||||||
# print('generating option')
|
|
||||||
var destination : String = option.destination
|
|
||||||
|
|
||||||
if option.label == null or option.label.empty():
|
if option.label == null or option.label.empty():
|
||||||
#jump to another node
|
emit(Constants.ByteCode.RunNode, node, [Program.Operand.new(destination)])
|
||||||
emit(Constants.ByteCode.RunNode,node,[Program.Operand.new(destination)])
|
|
||||||
else :
|
else :
|
||||||
var line_iD : String = ''#tags not supported TODO: ADD TAG SUPPORT
|
var line_id = '' #TODO: ADD TAG SUPPORT
|
||||||
var string_iD = register_string(option.label,node.name,line_iD,option.line_number,[])
|
var string_id = register_string(option.label, node.name, line_id, option.line_number, [])
|
||||||
|
|
||||||
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(string_iD),Program.Operand.new(destination)])
|
emit(Constants.ByteCode.AddOption, node, [Program.Operand.new(string_id), Program.Operand.new(destination)])
|
||||||
|
|
||||||
|
func generate_assignment(node, assignment):
|
||||||
#compile instructions for assigning values
|
|
||||||
func generate_assignment(node,assignment):
|
|
||||||
# print('generating assign')
|
|
||||||
#assignment
|
|
||||||
if assignment.operation == Constants.TokenType.EqualToOrAssign:
|
if assignment.operation == Constants.TokenType.EqualToOrAssign:
|
||||||
#evaluate the expression to a value for the stack
|
generate_expression(node, assignment.value)
|
||||||
generate_expression(node,assignment.value)
|
|
||||||
else :
|
else :
|
||||||
#this is combined op
|
emit(Constants.ByteCode.PushVariable, node, [assignment.destination])
|
||||||
#get value of var
|
generate_expression(node, assignment.value)
|
||||||
emit(Constants.ByteCode.PushVariable,node,[assignment.destination])
|
|
||||||
|
|
||||||
#evaluate the expression and push value to stack
|
|
||||||
generate_expression(node,assignment.value)
|
|
||||||
|
|
||||||
#stack contains oldvalue and result
|
|
||||||
|
|
||||||
match assignment.operation:
|
match assignment.operation:
|
||||||
Constants.TokenType.AddAssign:
|
Constants.TokenType.AddAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Add))])
|
Constants.ByteCode.CallFunc,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Add))]
|
||||||
|
)
|
||||||
Constants.TokenType.MinusAssign:
|
Constants.TokenType.MinusAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Minus))])
|
Constants.ByteCode.CallFunc,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Minus))]
|
||||||
|
)
|
||||||
Constants.TokenType.MultiplyAssign:
|
Constants.TokenType.MultiplyAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.MultiplyAssign))])
|
Constants.ByteCode.CallFunc,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.MultiplyAssign))]
|
||||||
|
)
|
||||||
Constants.TokenType.DivideAssign:
|
Constants.TokenType.DivideAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.DivideAssign))])
|
Constants.ByteCode.CallFunc,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.DivideAssign))]
|
||||||
|
)
|
||||||
_:
|
_:
|
||||||
printerr('Unable to generate assignment')
|
printerr('Unable to generate assignment')
|
||||||
|
|
||||||
#stack contains destination value
|
emit(Constants.ByteCode.StoreVariable, node, [Program.Operand.new(assignment.destination)])
|
||||||
#store the top of the stack in variable
|
emit(Constants.ByteCode.Pop, node)
|
||||||
emit(Constants.ByteCode.StoreVariable,node,[Program.Operand.new(assignment.destination)])
|
|
||||||
|
|
||||||
#clean stack
|
func generate_expression(node, expression):
|
||||||
emit(Constants.ByteCode.Pop,node)
|
|
||||||
|
|
||||||
|
|
||||||
#compile expression instructions
|
|
||||||
func generate_expression(node,expression):
|
|
||||||
# print('generating expression')
|
|
||||||
#expression = value or func call
|
|
||||||
match expression.type:
|
match expression.type:
|
||||||
Constants.ExpressionType.Value:
|
Constants.ExpressionType.Value:
|
||||||
generate_value(node,expression.value)
|
generate_value(node, expression.value)
|
||||||
Constants.ExpressionType.FunctionCall:
|
Constants.ExpressionType.FunctionCall:
|
||||||
#eval all parameters
|
for parameter in expression.parameters:
|
||||||
for param in expression.params:
|
generate_expression(node, parameter)
|
||||||
generate_expression(node,param)
|
|
||||||
|
|
||||||
#put the num of of params to stack
|
emit(Constants.ByteCode.PushNumber, node, [Program.Operand.new(expression.parameters.size())])
|
||||||
emit(Constants.ByteCode.PushNumber,node,[Program.Operand.new(expression.params.size())])
|
emit(Constants.ByteCode.CallFunc, node, [Program.Operand.new(expression.function)])
|
||||||
|
|
||||||
#call function
|
|
||||||
emit(Constants.ByteCode.CallFunc,node,[Program.Operand.new(expression.function)])
|
|
||||||
_:
|
_:
|
||||||
printerr('no expression')
|
printerr('No expression.')
|
||||||
|
|
||||||
#compile value instructions
|
func generate_value(node, value):
|
||||||
func generate_value(node,value):
|
|
||||||
# print('generating value')
|
|
||||||
#push value to stack
|
|
||||||
match value.value.type:
|
match value.value.type:
|
||||||
Constants.ValueType.Number:
|
Constants.ValueType.Number:
|
||||||
emit(Constants.ByteCode.PushNumber,node,[Program.Operand.new(value.value.as_number())])
|
emit(
|
||||||
|
Constants.ByteCode.PushNumber,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(value.value.as_number())]
|
||||||
|
)
|
||||||
Constants.ValueType.Str:
|
Constants.ValueType.Str:
|
||||||
var id = register_string(value.value.as_string(),
|
var id = register_string(
|
||||||
node.name,'',value.line_number,[])
|
value.value.as_string(),
|
||||||
emit(Constants.ByteCode.PushString,node,[Program.Operand.new(id)])
|
node.name,
|
||||||
|
'',
|
||||||
|
value.line_number,
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
emit(
|
||||||
|
Constants.ByteCode.PushString,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(id)]
|
||||||
|
)
|
||||||
Constants.ValueType.Boolean:
|
Constants.ValueType.Boolean:
|
||||||
emit(Constants.ByteCode.PushBool,node,[Program.Operand.new(value.value.as_bool())])
|
emit(
|
||||||
|
Constants.ByteCode.PushBool,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(value.value.as_bool())]
|
||||||
|
)
|
||||||
Constants.ValueType.Variable:
|
Constants.ValueType.Variable:
|
||||||
emit(Constants.ByteCode.PushVariable,node,[Program.Operand.new(value.value.variable)])
|
emit(
|
||||||
|
Constants.ByteCode.PushVariable,
|
||||||
|
node,
|
||||||
|
[Program.Operand.new(value.value.variable)]
|
||||||
|
)
|
||||||
Constants.ValueType.Nullean:
|
Constants.ValueType.Nullean:
|
||||||
emit(Constants.ByteCode.PushNull,node)
|
emit(Constants.ByteCode.PushNull, node)
|
||||||
_:
|
_:
|
||||||
printerr('Unrecognized valuenode type: %s' % value.value.type)
|
printerr('Unrecognized valuenode type: %s' % value.value.type)
|
||||||
|
|
||||||
static func print_tokens(tokens:Array=[]):
|
|
||||||
var list : PoolStringArray = []
|
|
||||||
list.append('\n')
|
|
||||||
for token in tokens:
|
|
||||||
list.append('%s (%s line %s)\n'%[Constants.token_type_name(token.type),token.value,token.line_number])
|
|
||||||
print('TOKENS:')
|
|
||||||
print(list.join(''))
|
|
||||||
|
|
|
@ -3,30 +3,29 @@ class_name Lexer
|
||||||
|
|
||||||
const Constants = preload('res://addons/Wol/core/constants.gd')
|
const Constants = preload('res://addons/Wol/core/constants.gd')
|
||||||
|
|
||||||
const LINE_COMENT : String = '//'
|
const LINE_COMENT = '//'
|
||||||
const FORWARD_SLASH : String = '/'
|
const FORWARD_SLASH = '/'
|
||||||
|
const LINE_SEPARATOR = '\n'
|
||||||
|
|
||||||
const LINE_SEPARATOR : String = '\n'
|
const BASE = 'base'
|
||||||
|
const DASH = '-'
|
||||||
|
const COMMAND = 'command'
|
||||||
|
const LINK = 'link'
|
||||||
|
const SHORTCUT = 'shortcut'
|
||||||
|
const TAG = 'tag'
|
||||||
|
const EXPRESSION = 'expression'
|
||||||
|
const ASSIGNMENT = 'assignment'
|
||||||
|
const OPTION = 'option'
|
||||||
|
const OR = 'or'
|
||||||
|
const DESTINATION = 'destination'
|
||||||
|
|
||||||
const BASE : String = 'base'
|
var WHITESPACE = '\\s*'
|
||||||
const DASH : String = '-'
|
|
||||||
const COMMAND : String = 'command'
|
|
||||||
const LINK : String = 'link'
|
|
||||||
const SHORTCUT : String = 'shortcut'
|
|
||||||
const TAG : String = 'tag'
|
|
||||||
const EXPRESSION : String = 'expression'
|
|
||||||
const ASSIGNMENT : String = 'assignment'
|
|
||||||
const OPTION : String = 'option'
|
|
||||||
const OR : String = 'or'
|
|
||||||
const DESTINATION : String = 'destination'
|
|
||||||
|
|
||||||
var WHITESPACE : String = '\\s*'
|
var _states = {}
|
||||||
|
var _defaultState
|
||||||
|
var _currentState
|
||||||
|
|
||||||
var _states : Dictionary = {}
|
var _indentStack = []
|
||||||
var _defaultState : LexerState
|
|
||||||
var _currentState : LexerState
|
|
||||||
|
|
||||||
var _indentStack : Array = []
|
|
||||||
var _shouldTrackIndent : bool = false
|
var _shouldTrackIndent : bool = false
|
||||||
|
|
||||||
var filename = ''
|
var filename = ''
|
||||||
|
@ -185,11 +184,11 @@ func tokenize():
|
||||||
_indentStack.push_front(IntBoolPair.new(0, false))
|
_indentStack.push_front(IntBoolPair.new(0, false))
|
||||||
_shouldTrackIndent = false
|
_shouldTrackIndent = false
|
||||||
|
|
||||||
var tokens : Array = []
|
var tokens = []
|
||||||
|
|
||||||
_currentState = _defaultState
|
_currentState = _defaultState
|
||||||
|
|
||||||
var lines : PoolStringArray = text.split(LINE_SEPARATOR)
|
var lines = text.split(LINE_SEPARATOR)
|
||||||
lines.append('')
|
lines.append('')
|
||||||
|
|
||||||
var line_number : int = 1
|
var line_number : int = 1
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
const Constants = preload('res://addons/Wol/core/constants.gd')
|
const Constants = preload('res://addons/Wol/core/constants.gd')
|
||||||
var Value = load('res://addons/Wol/core/value.gd')
|
const Value = preload('res://addons/Wol/core/value.gd')
|
||||||
|
|
||||||
const EXECUTION_COMPLETE : String = 'execution_complete_command'
|
|
||||||
|
|
||||||
var NULL_VALUE = Value.new(null)
|
|
||||||
|
|
||||||
# Function references to handlers
|
# Function references to handlers
|
||||||
var line_handler
|
var line_handler
|
||||||
|
@ -18,9 +14,9 @@ var dialogue_finished_handler
|
||||||
var dialogue
|
var dialogue
|
||||||
var libraries
|
var libraries
|
||||||
var program
|
var program
|
||||||
var _state
|
var state
|
||||||
|
|
||||||
var _currentNode
|
var current_node
|
||||||
|
|
||||||
var execution_state = Constants.ExecutionState.Stopped
|
var execution_state = Constants.ExecutionState.Stopped
|
||||||
|
|
||||||
|
@ -43,192 +39,155 @@ func _init(_dialogue, _libraries):
|
||||||
assert(command_handler.is_valid(), 'Cannot run without a command handler (_on_command)')
|
assert(command_handler.is_valid(), 'Cannot run without a command handler (_on_command)')
|
||||||
assert(node_start_handler.is_valid(), 'Cannot run without a node start handler (_on_node_start)')
|
assert(node_start_handler.is_valid(), 'Cannot run without a node start handler (_on_node_start)')
|
||||||
assert(node_finished_handler.is_valid(), 'Cannot run without a node finished handler (_on_node_finished)')
|
assert(node_finished_handler.is_valid(), 'Cannot run without a node finished handler (_on_node_finished)')
|
||||||
|
assert(dialogue_finished_handler.is_valid(), 'Cannot run without a dialogue finished handler (_on_dialogue_finished)')
|
||||||
|
|
||||||
_state = VmState.new()
|
state = VmState.new()
|
||||||
|
|
||||||
#set the node to run
|
#set the node to run
|
||||||
#return true if successeful false if no node
|
#return true if successeful false if no node
|
||||||
#of that name found
|
#of that name found
|
||||||
func set_node(name):
|
func set_node(name):
|
||||||
if program == null || program.nodes.size() == 0:
|
if program == null or program.nodes.size() == 0:
|
||||||
printerr('Could not load %s : no nodes loaded' % name)
|
printerr('Could not load %s : no nodes loaded' % name)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if !program.nodes.has(name):
|
if not program.nodes.has(name):
|
||||||
execution_state = Constants.ExecutionState.Stopped
|
execution_state = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
printerr('No node named %s has been loaded' % name)
|
printerr('No node named %s has been found in dialogue, so not loading' % name)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
_currentNode = program.nodes[name]
|
current_node = program.nodes[name]
|
||||||
reset()
|
reset()
|
||||||
_state.currentNodeName = name
|
state.current_node_name = name
|
||||||
node_start_handler.call_func(name)
|
node_start_handler.call_func(name)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func current_node_name()->String:
|
|
||||||
return _currentNode.nodeName
|
|
||||||
|
|
||||||
func current_node():
|
|
||||||
return _currentNode
|
|
||||||
|
|
||||||
func pause():
|
func pause():
|
||||||
execution_state = Constants.ExecutionState.Suspended
|
execution_state = Constants.ExecutionState.Suspended
|
||||||
|
|
||||||
#stop exectuion
|
|
||||||
func stop():
|
func stop():
|
||||||
execution_state = Constants.ExecutionState.Stopped
|
execution_state = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
_currentNode = null
|
current_node = null
|
||||||
|
|
||||||
#set the currently selected option and
|
|
||||||
#resume execution if waiting for result
|
|
||||||
#return false if error
|
|
||||||
func set_selected_option(id):
|
func set_selected_option(id):
|
||||||
if execution_state != Constants.ExecutionState.WaitingForOption:
|
if execution_state != Constants.ExecutionState.WaitingForOption:
|
||||||
printerr('Unable to select option when dialogue not waiting for option')
|
printerr('Unable to select option when dialogue not waiting for option')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if id < 0 or id >= _state.currentOptions.size():
|
if id < 0 or id >= state.current_options.size():
|
||||||
printerr('%d is not a valid option ' % id)
|
printerr('%d is not a valid option!' % id)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var destination = _state.currentOptions[id].value
|
var destination = state.current_options[id][1]
|
||||||
_state.push_value(destination)
|
state.push_value(destination)
|
||||||
_state.currentOptions.clear()
|
state.current_options.clear()
|
||||||
|
|
||||||
#no longer waiting for option
|
|
||||||
execution_state = Constants.ExecutionState.Suspended
|
execution_state = Constants.ExecutionState.Suspended
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func reset():
|
func reset():
|
||||||
_state = VmState.new()
|
state = VmState.new()
|
||||||
|
|
||||||
func get_next_instruction():
|
func get_next_instruction():
|
||||||
return null if _currentNode.instructions.size() - 1 <= _state.programCounter else _currentNode.instructions[_state.programCounter + 1]
|
if current_node.instructions.size() - 1 > state.programCounter:
|
||||||
|
return current_node.instructions[state.programCounter + 1]
|
||||||
|
return
|
||||||
|
|
||||||
func resume():
|
func resume():
|
||||||
if _currentNode == null:
|
if current_node == null:
|
||||||
printerr('Cannot run dialogue with no node selected')
|
printerr('Cannot run dialogue with no node selected')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if execution_state == Constants.ExecutionState.WaitingForOption:
|
if execution_state == Constants.ExecutionState.WaitingForOption:
|
||||||
printerr('Cannot run while waiting for option')
|
printerr('Cannot run while waiting for option')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
execution_state = Constants.ExecutionState.Running
|
execution_state = Constants.ExecutionState.Running
|
||||||
|
|
||||||
#execute instruction until something cool happens
|
#execute instruction until something cool happens
|
||||||
while execution_state == Constants.ExecutionState.Running:
|
while execution_state == Constants.ExecutionState.Running:
|
||||||
var currentInstruction = _currentNode.instructions[_state.programCounter]
|
var current_instruction = current_node.instructions[state.programCounter]
|
||||||
|
run_instruction(current_instruction)
|
||||||
|
state.programCounter += 1
|
||||||
|
|
||||||
run_instruction(currentInstruction)
|
if state.programCounter >= current_node.instructions.size():
|
||||||
_state.programCounter += 1
|
node_finished_handler.call_func(current_node.nodeName)
|
||||||
|
|
||||||
if _state.programCounter >= _currentNode.instructions.size():
|
|
||||||
node_finished_handler.call_func(_currentNode.nodeName)
|
|
||||||
execution_state = Constants.ExecutionState.Stopped
|
execution_state = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
dialogue_finished_handler.call_func()
|
dialogue_finished_handler.call_func()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func find_label_instruction(label:String)->int:
|
func find_label_instruction(label):
|
||||||
if !_currentNode.labels.has(label):
|
if not current_node.labels.has(label):
|
||||||
printerr('Unknown label:'+label)
|
printerr('Unknown label:' + label)
|
||||||
return -1
|
return -1
|
||||||
return _currentNode.labels[label]
|
return current_node.labels[label]
|
||||||
|
|
||||||
func run_instruction(instruction)->bool:
|
func run_instruction(instruction):
|
||||||
match instruction.operation:
|
match instruction.operation:
|
||||||
Constants.ByteCode.Label:
|
Constants.ByteCode.Label:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Jump to named label
|
||||||
Constants.ByteCode.JumpTo:
|
Constants.ByteCode.JumpTo:
|
||||||
#jump to named label
|
state.programCounter = find_label_instruction(instruction.operands[0].value) - 1
|
||||||
_state .programCounter = find_label_instruction(instruction.operands[0].value)-1
|
|
||||||
|
|
||||||
Constants.ByteCode.RunLine:
|
Constants.ByteCode.RunLine:
|
||||||
#look up string from string table
|
# Lookup string and give back as line
|
||||||
#pass it to client as line
|
|
||||||
var key = instruction.operands[0].value
|
var key = instruction.operands[0].value
|
||||||
|
|
||||||
var line = program.strings[key]
|
var line = program.strings[key]
|
||||||
|
|
||||||
#the second operand is the expression count
|
# The second operand is the expression count of format function
|
||||||
# of format function
|
# TODO: Add format functions supportk
|
||||||
if instruction.operands.size() > 1:
|
if instruction.operands.size() > 1:
|
||||||
pass#add format function support
|
pass
|
||||||
|
|
||||||
var pause = line_handler.call_func(line)
|
var return_state = line_handler.call_func(line)
|
||||||
|
|
||||||
if pause == Constants.HandlerState.PauseExecution:
|
if return_state == Constants.HandlerState.PauseExecution:
|
||||||
execution_state = Constants.ExecutionState.Suspended
|
execution_state = Constants.ExecutionState.Suspended
|
||||||
|
|
||||||
Constants.ByteCode.RunCommand:
|
Constants.ByteCode.RunCommand:
|
||||||
var commandText : String = instruction.operands[0].value
|
var command_text = instruction.operands[0].value
|
||||||
|
var command = Program.Command.new(command_text)
|
||||||
|
|
||||||
if instruction.operands.size() > 1:
|
var return_state = command_handler.call_func(command)
|
||||||
pass#add format function
|
if return_state == Constants.HandlerState.PauseExecution:
|
||||||
|
|
||||||
var command = Program.Command.new(commandText)
|
|
||||||
|
|
||||||
var pause = command_handler.call_func(command) as int
|
|
||||||
if pause == Constants.HandlerState.PauseExecution:
|
|
||||||
execution_state = Constants.ExecutionState.Suspended
|
execution_state = Constants.ExecutionState.Suspended
|
||||||
|
|
||||||
Constants.ByteCode.PushString:
|
Constants.ByteCode.PushString, \
|
||||||
#push String var to stack
|
Constants.ByteCode.PushNumber, \
|
||||||
_state.push_value(instruction.operands[0].value)
|
|
||||||
|
|
||||||
Constants.ByteCode.PushNumber:
|
|
||||||
#push number to stack
|
|
||||||
_state.push_value(instruction.operands[0].value)
|
|
||||||
|
|
||||||
Constants.ByteCode.PushBool:
|
Constants.ByteCode.PushBool:
|
||||||
#push boolean to stack
|
state.push_value(instruction.operands[0].value)
|
||||||
_state.push_value(instruction.operands[0].value)
|
|
||||||
|
|
||||||
Constants.ByteCode.PushNull:
|
Constants.ByteCode.PushNull:
|
||||||
#push null t
|
state.push_value(Value.new(null))
|
||||||
_state.push_value(NULL_VALUE)
|
|
||||||
|
|
||||||
|
# Jump to named label if value of stack top is false
|
||||||
Constants.ByteCode.JumpIfFalse:
|
Constants.ByteCode.JumpIfFalse:
|
||||||
#jump to named label if value of stack top is false
|
if not state.peek_value().as_bool():
|
||||||
if !_state.peek_value().as_bool():
|
state.programCounter = find_label_instruction(instruction.operands[0].value) - 1
|
||||||
_state.programCounter = find_label_instruction(instruction.operands[0].value)-1
|
|
||||||
|
|
||||||
|
# Jump to label whose name is on the stack
|
||||||
Constants.ByteCode.Jump:
|
Constants.ByteCode.Jump:
|
||||||
#jump to label whose name is on the stack
|
var destination = state.peek_value().as_string()
|
||||||
var dest : String = _state.peek_value().as_string()
|
state.programCounter = find_label_instruction(destination) - 1
|
||||||
_state.programCounter = find_label_instruction(dest)-1
|
|
||||||
|
|
||||||
Constants.ByteCode.Pop:
|
Constants.ByteCode.Pop:
|
||||||
#pop value from stack
|
state.pop_value()
|
||||||
_state.pop_value()
|
|
||||||
|
|
||||||
Constants.ByteCode.CallFunc:
|
Constants.ByteCode.CallFunc:
|
||||||
#call function with params on stack
|
var function_name = instruction.operands[0].value
|
||||||
#push any return value to stack
|
var function = libraries.get_function(function_name)
|
||||||
var functionName : String = instruction.operands[0].value
|
var expected_parameter_count = function.parameter_count
|
||||||
|
var actual_parameter_count = state.pop_value().as_number()
|
||||||
|
|
||||||
var function = libraries.get_function(functionName)
|
if expected_parameter_count > 0 \
|
||||||
|
and expected_parameter_count != actual_parameter_count:
|
||||||
var expected_parameter_count : int = function.paramCount
|
var error_data = [function_name, expected_parameter_count, actual_parameter_count]
|
||||||
var actual_parameter_count : int = _state.pop_value().as_number()
|
printerr('Function "%s" expected %d parameters but got %d instead' % error_data)
|
||||||
|
|
||||||
#if function takes in -1 params disregard
|
|
||||||
#expect the compiler to have placed the number of params
|
|
||||||
#at the top of the stack
|
|
||||||
if expected_parameter_count == -1:
|
|
||||||
expected_parameter_count = actual_parameter_count
|
|
||||||
|
|
||||||
if expected_parameter_count != actual_parameter_count:
|
|
||||||
printerr('Function %s expected %d parameters but got %d instead' %[functionName,
|
|
||||||
expected_parameter_count,actual_parameter_count])
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var result
|
var result
|
||||||
|
@ -236,85 +195,71 @@ func run_instruction(instruction)->bool:
|
||||||
if actual_parameter_count == 0:
|
if actual_parameter_count == 0:
|
||||||
result = function.invoke()
|
result = function.invoke()
|
||||||
else:
|
else:
|
||||||
var params : Array = []#value
|
var params = []
|
||||||
for _i in range(actual_parameter_count):
|
for _i in range(actual_parameter_count):
|
||||||
params.push_front(_state.pop_value())
|
params.push_front(state.pop_value())
|
||||||
|
|
||||||
result = function.invoke(params)
|
result = function.invoke(params)
|
||||||
|
|
||||||
if function.returnsValue:
|
if function.returns_value:
|
||||||
_state.push_value(result)
|
state.push_value(result)
|
||||||
|
|
||||||
Constants.ByteCode.PushVariable:
|
Constants.ByteCode.PushVariable:
|
||||||
#get content of variable and push to stack
|
var name = instruction.operands[0].value
|
||||||
var name : String = instruction.operands[0].value
|
|
||||||
# TODO: Reimplement variable storage
|
|
||||||
var loaded = dialogue.variable_storage.get_value(name)
|
var loaded = dialogue.variable_storage.get_value(name)
|
||||||
_state.push_value(loaded)
|
state.push_value(loaded)
|
||||||
|
|
||||||
Constants.ByteCode.StoreVariable:
|
Constants.ByteCode.StoreVariable:
|
||||||
#store top stack value to variable
|
var top = state.peek_value()
|
||||||
var top = _state.peek_value()
|
var destination = instruction.operands[0].value
|
||||||
var destination : String = instruction.operands[0].value
|
dialogue.variable_storage.set_value(destination, top)
|
||||||
dialogue.variable_storage.set_value(destination,top)
|
|
||||||
|
|
||||||
Constants.ByteCode.Stop:
|
Constants.ByteCode.Stop:
|
||||||
#stop execution and repost it
|
node_finished_handler.call_func(current_node.name)
|
||||||
node_finished_handler.call_func(_currentNode.name)
|
|
||||||
dialogue_finished_handler.call_func()
|
dialogue_finished_handler.call_func()
|
||||||
execution_state = Constants.ExecutionState.Stopped
|
execution_state = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
Constants.ByteCode.RunNode:
|
Constants.ByteCode.RunNode:
|
||||||
#run a node
|
var name = ''
|
||||||
var name : String
|
if instruction.operands.size() == 0 or instruction.operands[0].value.empty():
|
||||||
|
name = state.peek_value().value()
|
||||||
if (instruction.operands.size() == 0 || instruction.operands[0].value.empty()):
|
else:
|
||||||
#get string from stack and jump to node with that name
|
|
||||||
name = _state.peek_value().value()
|
|
||||||
else :
|
|
||||||
name = instruction.operands[0].value
|
name = instruction.operands[0].value
|
||||||
|
|
||||||
var pause = node_finished_handler.call_func(_currentNode.name)
|
var return_state = node_finished_handler.call_func(current_node.name)
|
||||||
set_node(name)
|
set_node(name)
|
||||||
_state.programCounter-=1
|
state.programCounter -= 1
|
||||||
if pause == Constants.HandlerState.PauseExecution:
|
if return_state == Constants.HandlerState.PauseExecution:
|
||||||
execution_state = Constants.ExecutionState.Suspended
|
execution_state = Constants.ExecutionState.Suspended
|
||||||
|
|
||||||
Constants.ByteCode.AddOption:
|
Constants.ByteCode.AddOption:
|
||||||
# add an option to current state
|
|
||||||
var key = instruction.operands[0].value
|
var key = instruction.operands[0].value
|
||||||
|
|
||||||
var line = program.strings[key]
|
var line = program.strings[key]
|
||||||
|
|
||||||
|
# TODO: Add format functions supportk
|
||||||
if instruction.operands.size() > 2:
|
if instruction.operands.size() > 2:
|
||||||
pass #formated text options
|
pass
|
||||||
|
|
||||||
# line to show and node name
|
state.current_options.append([line, instruction.operands[1].value])
|
||||||
_state.currentOptions.append(SimpleEntry.new(line, instruction.operands[1].value))
|
|
||||||
|
|
||||||
Constants.ByteCode.ShowOptions:
|
Constants.ByteCode.ShowOptions:
|
||||||
#show options - stop if none
|
if state.current_options.size() == 0:
|
||||||
if _state.currentOptions.size() == 0:
|
|
||||||
execution_state = Constants.ExecutionState.Stopped
|
execution_state = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
dialogue_finished_handler.call_func()
|
dialogue_finished_handler.call_func()
|
||||||
return false
|
return false
|
||||||
|
|
||||||
#present list of options
|
var choices = []
|
||||||
var choices : Array = []#Option
|
for option_index in range(state.current_options.size()):
|
||||||
for optionIndex in range(_state.currentOptions.size()):
|
var option = state.current_options[option_index]
|
||||||
var option : SimpleEntry = _state.currentOptions[optionIndex]
|
var line = option[0]
|
||||||
choices.append(Program.Option.new(option.key, optionIndex, option.value))
|
var destination = option[1]
|
||||||
|
choices.append(Program.Option.new(line, option_index, destination))
|
||||||
|
|
||||||
#we cant continue until option chosen
|
|
||||||
execution_state = Constants.ExecutionState.WaitingForOption
|
execution_state = Constants.ExecutionState.WaitingForOption
|
||||||
|
|
||||||
#pass the options to the client
|
|
||||||
#delegate for them to call
|
|
||||||
#when user makes selection
|
|
||||||
|
|
||||||
options_handler.call_func(choices)
|
options_handler.call_func(choices)
|
||||||
|
|
||||||
_:
|
_:
|
||||||
execution_state = Constants.ExecutionState.Stopped
|
execution_state = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
|
@ -324,12 +269,10 @@ func run_instruction(instruction)->bool:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
class VmState:
|
class VmState:
|
||||||
var Value = load('res://addons/Wol/core/value.gd')
|
var current_node_name = ''
|
||||||
|
var programCounter = 0
|
||||||
var currentNodeName : String
|
var current_options = []
|
||||||
var programCounter : int = 0
|
var stack = []
|
||||||
var currentOptions : Array = []#SimpleEntry
|
|
||||||
var stack : Array = [] #Value
|
|
||||||
|
|
||||||
func push_value(value)->void:
|
func push_value(value)->void:
|
||||||
if value is Value:
|
if value is Value:
|
||||||
|
@ -345,11 +288,3 @@ class VmState:
|
||||||
|
|
||||||
func clear_stack():
|
func clear_stack():
|
||||||
stack.clear()
|
stack.clear()
|
||||||
|
|
||||||
class SimpleEntry:
|
|
||||||
var key
|
|
||||||
var value
|
|
||||||
|
|
||||||
func _init(_key, _value):
|
|
||||||
key = _key
|
|
||||||
value = _value
|
|
||||||
|
|
Reference in a new issue