From 5183a02c6426d19699770c24ef4e22b12a00c992 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Fri, 13 May 2016 15:14:19 -0400 Subject: [PATCH] Implemented variables as well as ++, -- --- stdlib/ast_transformation.krak | 36 ++++++++-- stdlib/interpreter.krak | 121 ++++++++++++++++++++++++++++++--- 2 files changed, 142 insertions(+), 15 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index b602810..d8ec73a 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -690,6 +690,8 @@ obj ast_transformation (Object) { return assignment } fun transform_if_statement(node: *tree, scope: *ast_node, template_replacements: map): *ast_node { + if (get_node("AmbiguityInner", node)) + error(node, "Ambigious two ifs with one else!") var if_statement = ast_if_statement_ptr(transform_expression(get_node("boolean_expression", node), scope, template_replacements)) // one variable declarations might be in a code_block-less if statement add_to_scope("~enclosing_scope", scope, if_statement) @@ -1133,14 +1135,26 @@ fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { param_types = param_types.map(fun(t: *type): *type return t->clone_without_ref();) if (name == "==" || name == "!=" || name == ">" || name == "<" || name == "<=" || name == ">" || name == ">=" || name == "&&" || name == "||" || name == "!") return ast_function_ptr(name, type_ptr(param_types, type_ptr(base_type::boolean())), vector<*ast_node>(), false) - if (name == "." || name == "->") - return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>(), false) - if (name == "[]") - return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) + if (name == "." || name == "->") { + if (name == "->" && param_types[0]->indirection == 0) + error(string("drereferencing not a pointer: ") + name) + else + return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>(), false) + } + if (name == "[]") { + if (param_types[0]->indirection == 0) + error(string("drereferencing not a pointer: ") + name) + else + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) + } if (name == "&" && param_types.size == 1) return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_increased_indirection()), vector<*ast_node>(), false) - if (name == "\*" && param_types.size == 1) - return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) + if (name == "\*" && param_types.size == 1) { + if (param_types[0]->indirection == 0) + error(string("drereferencing not a pointer: ") + name) + else + return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) + } if (param_types.size > 1 && param_types[1]->rank() > param_types[0]->rank()) return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>(), false) return ast_function_ptr(name, type_ptr(param_types, param_types[0]), vector<*ast_node>(), false) @@ -1221,7 +1235,7 @@ fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool if (!func_param_types[j]->equality(param_types[j], false)) { /*println(string("types don't match ") + func_param_types[j]->to_string() + " with needed " + param_types[j]->to_string())*/ if (func_param_types[j]->to_string() == param_types[j]->to_string()) - error("types aren't equal, but their string rep is (and ref doesn't even matter)") + error(string("types aren't equal, but their string rep is (and ref doesn't even matter): ") + func_param_types[j]->to_string() + " vs " + param_types[j]->to_string() ) return false } } @@ -1347,6 +1361,14 @@ fun get_first_terminal(source: *tree): *tree { return null>() return get_first_terminal(source->children.first()) } +fun assert(works: bool, message: *char) { + if (!works) + error(message) +} +fun assert(works: bool, message: string) { + if (!works) + error(message) +} fun error(message: *char) error(string(message)); fun error(source: *tree, message: *char) error(source, string(message)); fun error(message: string) error(null>(), message); diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 035c13a..096bb9c 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -1,4 +1,5 @@ import io:* +import mem:* import map:* import stack:* import string:* @@ -6,13 +7,15 @@ import util:* import tree:* import symbol:* import ast_nodes:* +import type:* import ast_transformation:* adt value { integer: int, floating: float, - double_floating: double, - void_nothing + double_precision: double, + void_nothing, + variable: pair<*void,*type> } adt control_flow { nor, @@ -20,8 +23,78 @@ adt control_flow { bre, ret } +fun is_integer(it: value): bool { match(it) { value::integer(var) return true; } return false; } +fun is_floating(it: value): bool { match(it) { value::floating(var) return true; } return false; } +fun is_double_precision(it: value): bool { match(it) { value::double_precision(var) return true; } return false; } +fun is_void_nothing(it: value): bool { match(it) { value::void_nothing() return true; } return false; } +fun is_variable(it: value): bool { match(it) { value::variable(var) return true; } return false; } + +fun store_into_variable(to: value, from: value) { + assert(is_variable(to), "trying to store into not variable") + var variable = to.variable + // check for indirection + match (variable.second->base) { + /*base_type::object() return #sizeof<>*/ + /*base_type::adt() return #sizeof<>*/ + /*base_type::function() return #sizeof<>*/ + /*base_type::boolean() return *(variable.first) cast bool*/ + /*base_type::character() return *(variable.first) cast char*/ + /*base_type::ucharacter() return *(variable.first) cast uchar*/ + /*base_type::short_int() return *(variable.first) cast short*/ + /*base_type::ushort_int() return *(variable.first) cast ushort*/ + base_type::integer() { assert(is_integer(from), "mismatching assignemnt types"); *(variable.first) cast *int = from.integer; } + /*base_type::uinteger() return *(variable.first) cast uint*/ + /*base_type::long_int() return *(variable.first) cast long*/ + /*base_type::ulong_int() return *(variable.first) cast ulong*/ + base_type::floating() { assert(is_floating(from), "mismatching assignemnt types"); *(variable.first) cast *float = from.floating; } + base_type::double_precision() { assert(is_double_precision(from), "mismatching assignemnt types"); *(variable.first) cast *double = from.double_precision; } + } +} +fun get_real_value(v: value): value { + if (!is_variable(v)) + return v + var variable = v.variable + // check for indirection + match (variable.second->base) { + /*base_type::object() return #sizeof<>*/ + /*base_type::adt() return #sizeof<>*/ + /*base_type::function() return #sizeof<>*/ + /*base_type::boolean() return *(variable.first) cast bool*/ + /*base_type::character() return *(variable.first) cast char*/ + /*base_type::ucharacter() return *(variable.first) cast uchar*/ + /*base_type::short_int() return *(variable.first) cast short*/ + /*base_type::ushort_int() return *(variable.first) cast ushort*/ + base_type::integer() return value::integer(*(variable.first) cast *int) + /*base_type::uinteger() return *(variable.first) cast uint*/ + /*base_type::long_int() return *(variable.first) cast long*/ + /*base_type::ulong_int() return *(variable.first) cast ulong*/ + base_type::floating() return value::floating(*(variable.first) cast *float) + base_type::double_precision() return value::double_precision(*(variable.first) cast *double) + } + error("Cannot get real value from variable") +} +fun type_size(t: *type): ulong { + if (t->indirection) + return #sizeof<*void> + match (t->base) { + /*base_type::object() return #sizeof<>*/ + /*base_type::adt() return #sizeof<>*/ + /*base_type::function() return #sizeof<>*/ + base_type::boolean() return #sizeof + base_type::character() return #sizeof + base_type::ucharacter() return #sizeof + base_type::short_int() return #sizeof + base_type::ushort_int() return #sizeof + base_type::integer() return #sizeof + base_type::uinteger() return #sizeof + base_type::long_int() return #sizeof + base_type::ulong_int() return #sizeof + base_type::floating() return #sizeof + base_type::double_precision() return #sizeof + } +} fun print_value(v: ref value) { - match (v) { + match (get_real_value(v)) { value::integer(data) println(data) value::floating(data) println(data) value::void_nothing() println("void") @@ -65,7 +138,6 @@ obj interpreter (Object) { return make_pair(call_function(func_call->function_call.func, parameters, var_stack), control_flow::nor()) } fun call_function(func: *ast_node, parameters: vector, var_stack: *stack>): value { - var_stack->push(map()) // will need adjustment var func_name = func->function.name if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" @@ -74,6 +146,16 @@ obj interpreter (Object) { || func_name == "|" || func_name == "&" )) return do_basic_op(func_name, parameters[0], parameters[1]) + if (func_name == "++p" || func_name == "--p") { + var to_ret = get_real_value(parameters[0]) + store_into_variable(parameters[0], do_basic_op(func_name.slice(0,1), parameters[0], value::integer(1))) + return to_ret + } + if (func_name == "++" || func_name == "--") { + store_into_variable(parameters[0], do_basic_op(func_name.slice(0,1), parameters[0], value::integer(1))) + return get_real_value(parameters[0]) + } + var_stack->push(map()) if (parameters.size != func->function.parameters.size) error(string("calling function ") + func->function.name + " with wrong number of parameters") for (var i = 0; i < parameters.size; i++;) @@ -109,7 +191,27 @@ obj interpreter (Object) { return make_pair(value::void_nothing(), control_flow::nor()) } fun interpret_return_statement(stmt: *ast_node, var_stack: *stack>): pair { - return make_pair(interpret(stmt->return_statement.return_value, var_stack).first, control_flow::ret()) + return make_pair(get_real_value(interpret(stmt->return_statement.return_value, var_stack).first), control_flow::ret()) + } + fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack>): pair { + var ident_type = stmt->declaration_statement.identifier->identifier.type + var ident_name = stmt->declaration_statement.identifier->identifier.name + var_stack->top()[ident_name] = value::variable(make_pair(malloc(type_size(ident_type)),ident_type)) + if (stmt->declaration_statement.expression) + store_into_variable(var_stack->top()[ident_name], get_real_value(interpret(stmt->declaration_statement.expression, var_stack).first)) + return make_pair(value::void_nothing(), control_flow::nor()) + } + fun interpret_assignment_statement(stmt: *ast_node, var_stack: *stack>): pair { + var to = interpret(stmt->assignment_statement.to, var_stack).first + var from = interpret(stmt->assignment_statement.from, var_stack).first + store_into_variable(to, get_real_value(from)) + return make_pair(value::void_nothing(), control_flow::nor()) + } + fun interpret_identifier(ident: *ast_node, var_stack: *stack>): pair { + for (var i = 0; i < var_stack->size(); i++;) + if (var_stack->from_top(i).contains_key(ident->identifier.name)) + return make_pair(var_stack->from_top(i)[ident->identifier.name], control_flow::nor()) + error("Cannot find variable") } fun interpret_value(val: *ast_node): pair return make_pair(wrap_value(val), control_flow::nor()) @@ -119,14 +221,17 @@ obj interpreter (Object) { ast_node::statement(backing) return interpret_statement(node, var_stack) ast_node::code_block(backing) return interpret_code_block(node, var_stack) ast_node::return_statement(backing) return interpret_return_statement(node, var_stack) + ast_node::declaration_statement(backing) return interpret_declaration_statement(node, var_stack) + ast_node::assignment_statement(backing) return interpret_assignment_statement(node, var_stack) + ast_node::identifier(backing) return interpret_identifier(node, var_stack) ast_node::value(backing) return interpret_value(node) } error(string("Cannot interpret node: ") + get_ast_name(node)) } fun do_basic_op(func_name: string, a: value, b: value): value { - match (a) { + match (get_real_value(a)) { value::integer(av) { - match (b) { + match (get_real_value(b)) { value::integer(bv) return value::integer(do_op(func_name, av, bv)) } } @@ -172,7 +277,7 @@ obj interpreter (Object) { if (value_str[value_str.length()-1] == 'f') return value::floating(1.0f) else - return value::double_floating(1.0) + return value::double_precision(1.0) else return value::integer(string_to_int(value_str)) }