From 593877eb84b6b8da54a3af30a71daaaf7df5ad98 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 29 May 2016 23:54:54 -0700 Subject: [PATCH] Fixed returning out of loops/if as well as math and triple quoted strings --- stdlib/interpreter.krak | 73 +++++++++++++++++++++++++++++++++-------- stdlib/math.krak | 2 ++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index a85a367..25d4ac4 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -1,5 +1,6 @@ import io:* import mem:* +import math:* import map:* import stack:* import string:* @@ -66,7 +67,11 @@ fun wrap_value(val: *ast_node): value { var value_str = val->value.string_value if (value_str[0] == '"') { // " // Comment hack for emacs now var to_ret = string() - value_str = value_str.slice(1,-2) + // triple quoted strings + if (value_str[1] == '"' && value_str[2] == '"') + value_str = value_str.slice(3,-4) + else + value_str = value_str.slice(1,-2) for (var i = 0; i < value_str.length()-1; i++;) { if (value_str[i] == '\\' && value_str[i+1] == 'n') { to_ret += '\n' @@ -344,6 +349,7 @@ fun get_type_from_primitive_value(v: value): *type { value::floating(data) return type_ptr(base_type::floating()) value::double_precision(data) return type_ptr(base_type::double_precision()) value::pointer(data) return data.second + value::void_nothing() return type_ptr(base_type::void_return()) } println("Bad get_type_from_primitive_value!") print_value(v) @@ -599,7 +605,7 @@ obj interpreter (Object) { return make_pair(value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection())), control_flow::nor()) } // check for built-in-ish externs (everything the standard library needs) - if (func_name == "printf" || func_name == "malloc" || func_name == "free" || func_name == "fflush" || func_name == "snprintf") + if (func_name == "printf" || func_name == "malloc" || func_name == "free" || func_name == "fflush" || func_name == "snprintf" || func_name == "atan" || func_name == "atan2" || func_name == "acos" || func_name == "asin" || func_name == "tan" || func_name == "cos" || func_name == "sin") return make_pair(call_built_in_extern(func_name, parameters), control_flow::nor()) if (!func_call_func->function.body_statement) error(string("trying to call unsupported extern function: ") + func_name) @@ -711,6 +717,27 @@ obj interpreter (Object) { } else if (func_name == "exit") { assert(parameters.size == 1 && is_integer(parameters[0]), "Calling exit with wrong params") exit(parameters[0].integer) + } else if (func_name == "atan") { + assert(parameters.size == 1 && is_double_precision(parameters[0]), "Calling atan with wrong params") + return value::double_precision(atan(parameters[0].double_precision)) + } else if (func_name == "atan2") { + assert(parameters.size == 2 && is_double_precision(parameters[0]) && is_double_precision(parameters[1]), "Calling atan2 with wrong params") + return value::double_precision(atan2(parameters[0].double_precision, parameters[1].double_precision)) + } else if (func_name == "acos") { + assert(parameters.size == 1 && is_double_precision(parameters[0]), "Calling acos with wrong params") + return value::double_precision(acos(parameters[0].double_precision)) + } else if (func_name == "asin") { + assert(parameters.size == 1 && is_double_precision(parameters[0]), "Calling asin with wrong params") + return value::double_precision(asin(parameters[0].double_precision)) + } else if (func_name == "tan") { + assert(parameters.size == 1 && is_double_precision(parameters[0]), "Calling tan with wrong params") + return value::double_precision(tan(parameters[0].double_precision)) + } else if (func_name == "cos") { + assert(parameters.size == 1 && is_double_precision(parameters[0]), "Calling cos with wrong params") + return value::double_precision(cos(parameters[0].double_precision)) + } else if (func_name == "sin") { + assert(parameters.size == 1 && is_double_precision(parameters[0]), "Calling sin with wrong params") + return value::double_precision(sin(parameters[0].double_precision)) } else { error(string("trying to call invalid func: ") + func_name) } @@ -722,40 +749,56 @@ obj interpreter (Object) { fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { var_stack->push(map()) var inner_defer_stack = stack<*ast_node>() + var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) if (truthy(interpret(if_stmt->if_statement.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) { - interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) + value_from_inside = interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) } else if (if_stmt->if_statement.else_part) { - interpret(if_stmt->if_statement.else_part, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) + value_from_inside = interpret(if_stmt->if_statement.else_part, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) } interpret_from_defer_stack(&inner_defer_stack, var_stack, value::void_nothing(), enclosing_func) pop_and_free(var_stack) - return make_pair(value::void_nothing(), control_flow::nor()) + return value_from_inside } fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { var_stack->push(map()) var inner_defer_stack = stack<*ast_node>() - while (truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) { - interpret(while_loop->while_loop.statement, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) + var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + var going = true + while (going && truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) { + value_from_inside = interpret(while_loop->while_loop.statement, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) interpret_from_defer_stack(&inner_defer_stack, var_stack, value::void_nothing(), enclosing_func) inner_defer_stack.clear() + if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre()) + going = false + if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con()) + value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) } interpret_from_defer_stack(&inner_defer_stack, var_stack, value::void_nothing(), enclosing_func) pop_and_free(var_stack) - return make_pair(value::void_nothing(), control_flow::nor()) + return value_from_inside } fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node): pair { var defer_stack = stack<*ast_node>() var_stack->push(map()) + var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + var going = true interpret(for_loop->for_loop.init, var_stack, enclosing_object, enclosing_func, &defer_stack) while (truthy(interpret(for_loop->for_loop.condition, var_stack, enclosing_object, enclosing_func, &defer_stack).first)) { - interpret(for_loop->for_loop.body, var_stack, enclosing_object, enclosing_func, &defer_stack) - interpret(for_loop->for_loop.update, var_stack, enclosing_object, enclosing_func, &defer_stack) + value_from_inside = interpret(for_loop->for_loop.body, var_stack, enclosing_object, enclosing_func, &defer_stack) + if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre()) + going = false + if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con()) + value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + + // only run update if we're not breaking or continuing + if (going) + interpret(for_loop->for_loop.update, var_stack, enclosing_object, enclosing_func, &defer_stack) interpret_from_defer_stack(&defer_stack, var_stack, enclosing_object, enclosing_func) defer_stack.clear() } interpret_from_defer_stack(&defer_stack, var_stack, enclosing_object, enclosing_func) pop_and_free(var_stack) - return make_pair(value::void_nothing(), control_flow::nor()) + return value_from_inside } fun interpret_code_block(block: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { var_stack->push(map()) @@ -841,9 +884,13 @@ obj interpreter (Object) { var to = interpret(stmt->assignment_statement.to, var_stack, enclosing_object, enclosing_func, defer_stack).first var from = interpret(stmt->assignment_statement.from, var_stack, enclosing_object, enclosing_func, defer_stack).first assert(is_variable(to), "assigning into not a variable") - // first, we have to see if this is an object // always do cast now to make our best effort at assignment (assign into a double from a float, etc) - store_into_variable(to, cast_value(get_real_value(from), to.variable.second)) + // unless it's an object + var from_real = get_real_value(from) + if (is_object_like(from_real)) + store_into_variable(to, from_real) + else + store_into_variable(to, cast_value(from_real, to.variable.second)) return make_pair(value::void_nothing(), control_flow::nor()) } fun interpret_defer_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { diff --git a/stdlib/math.krak b/stdlib/math.krak index a48a435..3b36c31 100644 --- a/stdlib/math.krak +++ b/stdlib/math.krak @@ -1,3 +1,5 @@ +#link(m) + fun fibanacci(num: int): int { var l1 = 1 var l2 = 1