Skip to content

Commit

Permalink
Removed new keyword/syntax in favor of python-style class() instancing
Browse files Browse the repository at this point in the history
  • Loading branch information
nardo committed Nov 22, 2009
1 parent fa9deb0 commit dab8511
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 88 deletions.
17 changes: 0 additions & 17 deletions interpreter/kt_compiler.py
Expand Up @@ -902,23 +902,6 @@ def _analyze_expr_map_expr(self, si, expr, valid_types, is_lvalue):

def _compile_expr_map_expr(self, si, expr, valid_types, is_lvalue):
return ('map', [(self.compile_expression(si, pair['key'], ('any'), False), self.compile_expression(si, pair['value'], ('any'), False)) for pair in expr['map_pairs']])

def _analyze_expr_new_object_expr(self, si, expr, valid_types, is_lvalue):
if is_lvalue:
raise compile_error, (expr, "new expression cannot be an lvalue.")
# search the global container
node = self.find_node(si.compound_node, expr['parent_name'])
if not node:
raise compile_error, (expr, "locator " + locator_name + " not found.")
expr['location'] = ('global_node', node)
if not (node.type == 'class' or node.type == 'struct'):
raise compile_error, (expr, "new only allowed for classes and structs.")
for arg in expr['argument_expr_list']:
self.analyze_expression(si, arg, ('any'), False)

def _compile_expr_new_object_expr(self, si, expr, valid_types, is_lvalue):
return ('new', expr['location'], [self.compile_expression(si, arg, ('any'), False) for arg in expr['argument_expr_list']])




71 changes: 33 additions & 38 deletions interpreter/kt_vm.py
Expand Up @@ -21,6 +21,11 @@ def __init__(self, vm, error_string):
self.error_string = error_string

class vm:
class function_record_instance:
def __init__(self, record):
self.function_record = record
def call(self, vm, reference_object, parameters):
vm.invoke_function_record(self.function_record, reference_object, parameters)
class object_instance:
def __init__(self, node):
self.id = node.compound_record
Expand All @@ -32,18 +37,28 @@ def __init__(self, node):
self.node = node
self.compound_record = node.compound_record
def eval(self, vm):
return self
return (self, None)
def call(self, vm, reference_object, params):
result = vm.object_instance(self.node)
if self.node.constructor_index is not None:
vm.invoke_function_record(vm.image.functions[self.node.constructor_index], result, params)
vm.return_value = result

class function_instance:
def __init__(self, node):
self.func_record = node.func_record
self.container_index = node.container.global_index
def eval(self, vm):
return ('func_rec', self.func_record, vm.globals[self.container_index])
return (self, vm.globals[self.container_index])
def call(self, vm, reference_object, params):
return vm.invoke_function_record(self.func_record, reference_object, params)
class python_function_instance:
def __init__(self, node):
self.python_function = node.python_function
def eval(self, vm):
return ('py_func', self.python_function)
return (self, None)
def call(self, vm, reference_object, params):
self.python_function(*params)
class python_class_instance:
def __init__(self, node):
self.python_class = node.python_class
Expand Down Expand Up @@ -82,26 +97,24 @@ def __init__(self, compiled_image):
self.return_value = None
for o in (o for o in compiled_image.globals_list if o.type == 'object'):
if o.constructor_index is not None:
callable = ('func_rec', compiled_image.functions[o.constructor_index], self.globals[o.global_index])
callable = (vm.function_record_instance(compiled_image.functions[o.constructor_index]), self.globals[o.global_index])
self.call_function(callable, ())

def exec_function(self, func_name, args):
func_node = self.image.find_node(None, func_name, lambda x: x.type =='function' )
self.call_function(self.globals[func_node.global_index].eval(self), ())

def call_function(self, callable, arguments):
if callable[0] == 'func_rec':
function_record = callable[1]
reference_object = callable[2]
new_frame = vm.frame(function_record, arguments, self.tos, reference_object)
self.tos = new_frame
def invoke_function_record(self, function_record, reference_object, arguments):
new_frame = vm.frame(function_record, arguments, self.tos, reference_object)
self.tos = new_frame
result = self.exec_current_instruction()
while result == Exec_Normal:
result = self.exec_current_instruction()
while result == Exec_Normal:
result = self.exec_current_instruction()
self.tos = self.tos.prev_frame
return result
elif callable[0] == 'py_func':
callable[1](*arguments)
self.tos = self.tos.prev_frame
return result

def call_function(self, callable, arguments):
callable[0].call(self, callable[1], arguments)

def exec_current_instruction(self):
instruction = self.tos.function_record.statements[self.tos.ip]
Expand Down Expand Up @@ -236,7 +249,7 @@ def _eval_global_node(self, node):
return self.globals[node.global_index].eval(self)
def _eval_sub_function(self, sub_function_index):
# callables are (function_record, reference_object) pairs
return ('func_rec', self.image.functions[sub_function_index], self.tos)
return (vm.function_record_instance(self.image.functions[sub_function_index]), self.tos)
def _eval_string_constant(self, value):
return value
def _eval_int_constant(self, value):
Expand Down Expand Up @@ -266,11 +279,11 @@ def _eval_imethod(self, imethod_index):
reference_object = self.tos.reference_object
method = reference_object.id.vtable[imethod_index]
spew("imethod: " + str(reference_object))
return ('func_rec', method, reference_object)
return (vm.function_record_instance(method), reference_object)
def _eval_selfmethod_global(self, global_index):
reference_object = self.tos.reference_object
method = self.image.functions[global_index]
return ('func_rec', method, reference_object)
return (vm.function_record_instance(method), reference_object)
def _eval_ivar(self, ivar_index):
return self.tos.reference_object.slots[ivar_index]

Expand All @@ -283,7 +296,7 @@ def _eval_slot(self, object_expr, slot_name):
if the_slot.type == 'variable':
return the_object.slots[the_slot.index]
elif the_slot.type == 'function':
return ('func_rec', the_object.id.vtable[the_slot.index], the_object)
return (vm.function_record_instance(the_object.id.vtable[the_slot.index]), the_object)

#conditional_expr
# test_expression
Expand Down Expand Up @@ -319,24 +332,6 @@ def _eval_map(self, map_pairs_list):
value = self.eval(pair[1])
result[key] = value
return result
#new_object_expr
# parent_name
# argument_expr_list

def _eval_new(self, class_node, args):
cnode = self.eval(class_node)
result = vm.object_instance(cnode.node)
evaluated_args = [self.eval(arg) for arg in args]
if cnode.node.constructor_index is not None:
callable = ('func_rec', self.image.functions[cnode.node.constructor_index], result)
self.call_function(callable, evaluated_args)
return result


#new_object_expr_type_expr
# parent_name_expr
# argument_expr_list


#('prev_scope', ()) - a reference to a variable in a previous scope
#('local', local_index) - local variable
Expand Down
1 change: 0 additions & 1 deletion parser/lexical_analyzer.flex
Expand Up @@ -459,7 +459,6 @@ COMMENT "//"[^\n\r]*
"switch" return rwSWITCH;
"case" return rwCASE;
"default" return rwDEFAULT;
"new" return rwNEW;
"var" return rwVAR;
"file" return rwFILE;

Expand Down
33 changes: 3 additions & 30 deletions parser/parser.bison
Expand Up @@ -63,7 +63,6 @@ void kt_error (struct YYLTYPE *loc, kt_lexer *lexer, parse_result *result, const
%token rwSWITCH "switch"
%token rwCASE "case"
%token rwDEFAULT "default"
%token rwNEW "new"
%token rwVAR "var"
%token rwINTEGER "integer"
%token rwFLOAT "float"
Expand Down Expand Up @@ -1076,15 +1075,14 @@ strcat_expression
}
;

new_or_func_expression
strcat_or_func_expression
: strcat_expression
| new_expression
| function_expression
;

conditional_expression
: new_or_func_expression
| new_or_func_expression '?' expression ':' conditional_expression
: strcat_or_func_expression
| strcat_or_func_expression '?' expression ':' conditional_expression
{
$$ = node(conditional_expr);
field($$, test_expression, $1);
Expand Down Expand Up @@ -1220,31 +1218,6 @@ function_expression
}
;

new_expression
: "new" locator optional_argument_specifier
{
$$ = node(new_object_expr);
field($$, parent_name, $2);
field($$, argument_expr_list, $3);
}
| "new" '(' expression ')' optional_argument_specifier
{
$$ = node(new_object_expr_type_expr);
field($$, parent_name_expr, $3);
field($$, argument_expr_list, $5);
}
;

optional_argument_specifier
:
{ $$ = empty_list(); }
| '(' ')'
{ $$ = empty_list(); }
| '(' argument_expression_list ')'
{ $$ = $2; }
;


%%

void kt_error (struct YYLTYPE *loc, kt_lexer *lexer, parse_result *result, const char *format, ...)
Expand Down
6 changes: 4 additions & 2 deletions test/test3/inheritance_test.kt
Expand Up @@ -37,5 +37,7 @@ function main()
'container/sub_object2'.do_print()
sub_object2.do_print()
'container2/sub_object2'.do_print()
var object3 = new test_subclass(100, 200)
object3.do_print()
//var object3 = new test_subclass(100, 200)
//object3.do_print()
var object4 = test_subclass("foo", "bar")
object4.do_print()

0 comments on commit dab8511

Please sign in to comment.