From 4dcd4f97151bc529dd894924082d1fa1fd58bfaf Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 15 May 2016 22:05:12 -0700 Subject: [PATCH] Added basic in single method access of member variables --- stdlib/c_generator.krak | 28 ++-- stdlib/interpreter.krak | 276 +++++++++++++++++++++++++--------------- 2 files changed, 191 insertions(+), 113 deletions(-) diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index bcefdfa..0baf454 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -72,7 +72,18 @@ obj code_triple (Object) { return pre+value+post } } - +fun is_dot_style_method_call(node: *ast_node): bool { + return is_function_call(node->function_call.func) && + is_function(node->function_call.func->function_call.func) && + (node->function_call.func->function_call.func->function.name == "->" || node->function_call.func->function_call.func->function.name == ".") && + is_function(node->function_call.func->function_call.parameters[1]) && + (is_type_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]) || + // or if it's a templated method (yes, this has gotten uuuuugly) + is_type_def(get_ast_scope(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])->get(string("~enclosing_scope"))[0]) || + // or it's in an adt + is_adt_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])) + // should get uglier when we have to figure out if it's just an inside lambda +} obj c_generator (Object) { var id_counter: int var ast_to_syntax: map<*ast_node, *tree> @@ -756,16 +767,11 @@ obj c_generator (Object) { var func_return_type = get_ast_type(node) // handle the obj.method() style of method call - var dot_style_method_call = is_function_call(node->function_call.func) && - is_function(node->function_call.func->function_call.func) && - (node->function_call.func->function_call.func->function.name == "->" || node->function_call.func->function_call.func->function.name == ".") && - is_function(node->function_call.func->function_call.parameters[1]) && - (is_type_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0]) || - // or if it's a templated method (yes, this has gotten uuuuugly) - is_type_def(get_ast_scope(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])->get(string("~enclosing_scope"))[0]) || - // or it's in an adt - is_adt_def(get_ast_scope(node->function_call.func->function_call.parameters[1])->get(string("~enclosing_scope"))[0])) - // should get uglier when we have to figure out if it's just an inside lambda + // Note that this function may not be 100% reliable + // There may be a problem around detecting properly + // inside of lambdas. Gotta move it out so the interpreter + // can use it too, though. + var dot_style_method_call = is_dot_style_method_call(node) if (dot_style_method_call) { func_name = generate_function(node->function_call.func->function_call.parameters[1], enclosing_object, enclosing_func, false, false).one_string() diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index d49c16f..f18bfc2 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -9,6 +9,8 @@ import symbol:* import ast_nodes:* import type:* import ast_transformation:* +// for is_dot_style_method_call +import c_generator:* // there is never an object literal/primitive // they remain wrapped in a variable value @@ -60,6 +62,53 @@ fun raw_to_value(data:float): value fun raw_to_value(data:double): value return value::double_precision(data) +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) + for (var i = 0; i < value_str.length()-1; i++;) { + if (value_str[i] == '\\' && value_str[i+1] == 'n') { + to_ret += '\n' + i++ + } else if (value_str[i] == '\\' && value_str[i+1] == 't') { + to_ret += '\t' + i++ + } else if (i == value_str.length()-2) { + to_ret += value_str[i] + to_ret += value_str[i+1] + } else { + to_ret += value_str[i] + } + } + return value::pointer(make_pair((to_ret.toCharArray()) cast *void, get_ast_type(val))) + } else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course) + return value::character(value_str[1]) + else if (value_str == "true") + return value::boolean(true) + else if (value_str == "false") + return value::boolean(false) + else { + // should differentiate between float and double... + var contains_dot = false + for (var i = 0; i < value_str.length(); i++;) { + if (value_str[i] == '.') { + contains_dot = true + break + } + } + if (contains_dot) + if (value_str[value_str.length()-1] == 'f') + return value::floating((string_to_double(value_str.slice(0,-2))) cast float) + else + return value::double_precision(string_to_double(value_str)) + else + return value::integer(string_to_int(value_str)) + } + error("Could not wrap value") + return value::void_nothing() +} + fun is_boolean(it: value): bool { match(it) { value::boolean(var) return true; } return false; } fun is_character(it: value): bool { match(it) { value::character(var) return true; } return false; } fun is_ucharacter(it: value): bool { match(it) { value::ucharacter(var) return true; } return false; } @@ -123,6 +172,8 @@ fun do_basic_op(func_name: string, a: value, b: value): value { value::uinteger(av) return do_basic_op_second_half(func_name, av, b, null()) value::long_int(av) return do_basic_op_second_half(func_name, av, b, null()) value::ulong_int(av) return do_basic_op_second_half(func_name, av, b, null()) + value::floating(av) return do_basic_floating_op_second_half(func_name, av, b, null()) + value::double_precision(av) return do_basic_floating_op_second_half(func_name, av, b, null()) value::pointer(av) { var inc_in_bytes = cast_value(b, type_ptr(base_type::ulong_int())).ulong_int * type_size(av.second->clone_with_decreased_indirection()) var ptr = null() @@ -135,6 +186,8 @@ fun do_basic_op(func_name: string, a: value, b: value): value { } return value::pointer(make_pair(ptr, av.second)) } + value::void_nothing() error(string("basic op called with void_nothing as first param: ") + func_name) + value::object_like() error(string("basic op called with object_like as first param: ") + func_name) } error(string("basic op called with something wrong as first param: ") + func_name) } @@ -150,9 +203,14 @@ fun do_basic_op_second_half(func_name: string, av: T, b: value, ptr_type: *ty value::uinteger(bv) return do_op(func_name, av, bv, ptr_type) value::long_int(bv) return do_op(func_name, av, bv, ptr_type) value::ulong_int(bv) return do_op(func_name, av, bv, ptr_type) + value::floating(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::double_precision(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::void_nothing() error(string("basic op called with void_nothing as second param: ") + func_name) + value::object_like() error(string("basic op called with object_like as second param: ") + func_name) // if one is a pointer, we want it to be a value::pointer(bv) return do_basic_op(func_name, b, raw_to_value(av)) } + print_value(b) error(string("basic op called with something wrong as second param: ") + func_name) } fun do_op(op: string, a: T, b: U, ptr_type: *type): value { @@ -170,7 +228,41 @@ fun do_op(op: string, a: T, b: U, ptr_type: *type): value { if (op == "^") return raw_to_value(a ^ b) if (op == "|") return raw_to_value(a | b) if (op == "&") return raw_to_value(a & b) - + error(("Invalid op: ") + op) +} +fun do_basic_floating_op_second_half(func_name: string, av: T, b: value, ptr_type: *type): value { + // because of the trickery in do_basic_op, if either param is a pointer, it's b + match (get_real_value(b)) { + value::boolean(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::character(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::ucharacter(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::short_int(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::ushort_int(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::integer(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::uinteger(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::long_int(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::ulong_int(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::floating(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::double_precision(bv) return do_floating_op(func_name, av, bv, ptr_type) + value::void_nothing() error(string("basic op called with void_nothing as second param: ") + func_name) + value::object_like() error(string("basic op called with object_like as second param: ") + func_name) + // if one is a pointer, we want it to be a + value::pointer(bv) return do_basic_op(func_name, b, raw_to_value(av)) + } + print_value(b) + error(string("basic op called with something wrong as second param: ") + func_name) +} +fun do_floating_op(op: string, a: T, b: U, ptr_type: *type): value { + if (op == "+") return raw_to_value(a + b) + if (op == "-") return raw_to_value(a - b) + if (op == "*") return raw_to_value(a * b) + if (op == "/") return raw_to_value(a / b) + if (op == "<") return raw_to_value(a < b) + if (op == ">") return raw_to_value(a > b) + if (op == "<=") return raw_to_value(a <= b) + if (op == ">=") return raw_to_value(a >= b) + if (op == "==") return raw_to_value(a == b) + if (op == "!=") return raw_to_value(a != b) error(("Invalid op: ") + op) } fun store_into_variable(to: value, from: value) { @@ -379,33 +471,47 @@ obj interpreter (Object) { println("calling main!") println("=============") var var_stack = stack>() - var result = call_function(results[0], vector(), &var_stack) + var result = call_function(results[0], vector(), &var_stack, value::void_nothing()) println("=============") println("Main returned: ") print_value(result) println("=============") } - fun interpret_function_call(func_call: *ast_node, var_stack: *stack>): pair { + fun interpret_function_call(func_call: *ast_node, var_stack: *stack>, enclosing_object: value): pair { + var func_call_parameters = func_call->function_call.parameters + var func_call_func = func_call->function_call.func + var new_enclosing_object = value::void_nothing() + // note here also that this is likely not a foolproof method + if (is_dot_style_method_call(func_call)) { + println("DOT STYLE METHOD CALL") + new_enclosing_object = get_real_value(interpret(func_call_func->function_call.parameters[0], var_stack, enclosing_object).first) + // do a dereference + if (is_pointer(new_enclosing_object)) + new_enclosing_object = get_real_value(value::variable(make_pair(new_enclosing_object.pointer.first, new_enclosing_object.pointer.second->clone_with_decreased_indirection()))) + func_call_func = func_call_func->function_call.parameters[1] + } + // check if it's a same method method call and do the right new_enclosing_object + // new_enclosing_object = enclosing_object + var func_name = func_call_func->function.name // some of these have to be done before parameters are evaluated (&&, ||, ., ->) - var func_name = func_call->function_call.func->function.name if (func_name == "&&" || func_name == "||") { - var p1true = truthy(get_real_value(interpret(func_call->function_call.parameters[0], var_stack).first)) + var p1true = truthy(get_real_value(interpret(func_call_parameters[0], var_stack, enclosing_object).first)) if ( (func_name == "&&" && !p1true) || (func_name == "||" && p1true) ) return make_pair(value::boolean(p1true), control_flow::nor()) - return make_pair(value::boolean(truthy(get_real_value(interpret(func_call->function_call.parameters[1], var_stack).first))), control_flow::nor()) + return make_pair(value::boolean(truthy(get_real_value(interpret(func_call_parameters[1], var_stack, enclosing_object).first))), control_flow::nor()) } else if (func_name == "." || func_name == "->") { - var left_side = get_real_value(interpret(func_call->function_call.parameters[0], var_stack).first) + var left_side = get_real_value(interpret(func_call_parameters[0], var_stack, enclosing_object).first) var ret_ptr = null() if (func_name == "->") - ret_ptr = ((left_side.pointer.first) cast *char + offset_into_struct(left_side.pointer.second->clone_with_decreased_indirection(), func_call->function_call.parameters[1])) cast *void + ret_ptr = ((left_side.pointer.first) cast *char + offset_into_struct(left_side.pointer.second->clone_with_decreased_indirection(), func_call_parameters[1])) cast *void else - ret_ptr = ((left_side.object_like.first) cast *char + offset_into_struct(left_side.object_like.second, func_call->function_call.parameters[1])) cast *void - return make_pair(value::variable(make_pair(ret_ptr, func_call->function_call.parameters[1]->identifier.type)), control_flow::nor()) + ret_ptr = ((left_side.object_like.first) cast *char + offset_into_struct(left_side.object_like.second, func_call_parameters[1])) cast *void + return make_pair(value::variable(make_pair(ret_ptr, func_call_parameters[1]->identifier.type)), control_flow::nor()) } - var parameters = func_call->function_call.parameters.map(fun(p: *ast_node): value return interpret(p, var_stack).first;) - return make_pair(call_function(func_call->function_call.func, parameters, var_stack), control_flow::nor()) + var parameters = func_call_parameters.map(fun(p: *ast_node): value return interpret(p, var_stack, enclosing_object).first;) + return make_pair(call_function(func_call_func, parameters, var_stack, new_enclosing_object), control_flow::nor()) } - fun call_function(func: *ast_node, parameters: vector, var_stack: *stack>): value { + fun call_function(func: *ast_node, parameters: vector, var_stack: *stack>, enclosing_object: value): value { // will need adjustment var func_name = func->function.name if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" @@ -447,16 +553,18 @@ obj interpreter (Object) { if (!func->function.body_statement) error(string("trying to call unsupported extern function: ") + func_name) // do regular function - var_stack->push(map()) + var new_var_stack = stack>() + new_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++;) { var param_type = get_ast_type(func)->parameter_types[i] - var_stack->top()[func->function.parameters[i]->identifier.name] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) - store_into_variable(var_stack->top()[func->function.parameters[i]->identifier.name], get_real_value(parameters[i])) + new_var_stack.top()[func->function.parameters[i]->identifier.name] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) + store_into_variable(new_var_stack.top()[func->function.parameters[i]->identifier.name], get_real_value(parameters[i])) } - var to_ret = interpret(func->function.body_statement, var_stack).first - pop_and_free(var_stack) + var to_ret = interpret(func->function.body_statement, &new_var_stack, enclosing_object).first + // need to handle copying out object before pop_and_free deletes them + pop_and_free(&new_var_stack) return to_ret } fun call_built_in_extern(func_name: string, parameters: vector): value { @@ -487,41 +595,41 @@ obj interpreter (Object) { } return value::void_nothing() } - fun interpret_statement(stmt: *ast_node, var_stack: *stack>): pair { - return interpret(stmt->statement.child, var_stack) + fun interpret_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value): pair { + return interpret(stmt->statement.child, var_stack, enclosing_object) } - fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack>): pair { + fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack>, enclosing_object: value): pair { var_stack->push(map()) - if (truthy(interpret(if_stmt->if_statement.condition, var_stack).first)) { - interpret(if_stmt->if_statement.then_part, var_stack) + if (truthy(interpret(if_stmt->if_statement.condition, var_stack, enclosing_object).first)) { + interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object) } else if (if_stmt->if_statement.else_part) { - interpret(if_stmt->if_statement.else_part, var_stack) + interpret(if_stmt->if_statement.else_part, var_stack, enclosing_object) } pop_and_free(var_stack) return make_pair(value::void_nothing(), control_flow::nor()) } - fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack>): pair { + fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack>, enclosing_object: value): pair { var_stack->push(map()) - while (truthy(interpret(while_loop->while_loop.condition, var_stack).first)) { - interpret(while_loop->while_loop.statement, var_stack) + while (truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object).first)) { + interpret(while_loop->while_loop.statement, var_stack, enclosing_object) } pop_and_free(var_stack) return make_pair(value::void_nothing(), control_flow::nor()) } - fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack>): pair { + fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack>, enclosing_object: value): pair { var_stack->push(map()) - interpret(for_loop->for_loop.init, var_stack) - while (truthy(interpret(for_loop->for_loop.condition, var_stack).first)) { - interpret(for_loop->for_loop.body, var_stack) - interpret(for_loop->for_loop.update, var_stack) + interpret(for_loop->for_loop.init, var_stack, enclosing_object) + while (truthy(interpret(for_loop->for_loop.condition, var_stack, enclosing_object).first)) { + interpret(for_loop->for_loop.body, var_stack, enclosing_object) + interpret(for_loop->for_loop.update, var_stack, enclosing_object) } pop_and_free(var_stack) return make_pair(value::void_nothing(), control_flow::nor()) } - fun interpret_code_block(block: *ast_node, var_stack: *stack>): pair { + fun interpret_code_block(block: *ast_node, var_stack: *stack>, enclosing_object: value): pair { var_stack->push(map()) for (var i = 0; i < block->code_block.children.size; i++;) { - var statement = interpret(block->code_block.children[i], var_stack) + var statement = interpret(block->code_block.children[i], var_stack, enclosing_object) match (statement.second) { control_flow::con() { pop_and_free(var_stack) @@ -541,34 +649,44 @@ obj interpreter (Object) { pop_and_free(var_stack) return make_pair(value::void_nothing(), control_flow::nor()) } - fun interpret_return_statement(stmt: *ast_node, var_stack: *stack>): pair { - return make_pair(get_real_value(interpret(stmt->return_statement.return_value, var_stack).first), control_flow::ret()) + fun interpret_return_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value): pair { + return make_pair(get_real_value(interpret(stmt->return_statement.return_value, var_stack, enclosing_object).first), control_flow::ret()) } - fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack>): pair { + fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value): 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)) + store_into_variable(var_stack->top()[ident_name], get_real_value(interpret(stmt->declaration_statement.expression, var_stack, enclosing_object).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 + fun interpret_assignment_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value): pair { + var to = interpret(stmt->assignment_statement.to, var_stack, enclosing_object).first + var from = interpret(stmt->assignment_statement.from, var_stack, enclosing_object).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)) return make_pair(value::void_nothing(), control_flow::nor()) } - fun interpret_identifier(ident: *ast_node, var_stack: *stack>): pair { + fun interpret_identifier(ident: *ast_node, var_stack: *stack>, enclosing_object: value): 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()) + // check for object member + if (is_object_like(enclosing_object)) { + var object_def = enclosing_object.object_like.second->type_def + for (var i = 0; i < object_def->type_def.variables.size; i++;) { + if (object_def->type_def.variables[i]->declaration_statement.identifier == ident) { + var ret_ptr = ((enclosing_object.object_like.first) cast *char + offset_into_struct(enclosing_object.object_like.second, ident)) cast *void + return make_pair(value::variable(make_pair(ret_ptr, ident->identifier.type)), control_flow::nor()) + } + } + } error(string("Cannot find variable: ") + ident->identifier.name) } - fun interpret_cast(node: *ast_node, var_stack: *stack>): pair { - return make_pair(cast_value(interpret(node->cast.value, var_stack).first, node->cast.to_type), control_flow::nor()) + fun interpret_cast(node: *ast_node, var_stack: *stack>, enclosing_object: value): pair { + return make_pair(cast_value(interpret(node->cast.value, var_stack, enclosing_object).first, node->cast.to_type), control_flow::nor()) } fun interpret_compiler_intrinsic(node: *ast_node, var_stack: *stack>): pair { var intrinsic_name = node->compiler_intrinsic.intrinsic @@ -578,69 +696,23 @@ obj interpreter (Object) { } fun interpret_value(val: *ast_node): pair return make_pair(wrap_value(val), control_flow::nor()) - fun interpret(node: *ast_node, var_stack: *stack>): pair { + fun interpret(node: *ast_node, var_stack: *stack>, enclosing_object: value): pair { match (*node) { - ast_node::function_call(backing) return interpret_function_call(node, var_stack) - ast_node::statement(backing) return interpret_statement(node, var_stack) - ast_node::if_statement(backing) return interpret_if_statement(node, var_stack) - ast_node::while_loop(backing) return interpret_while_loop(node, var_stack) - ast_node::for_loop(backing) return interpret_for_loop(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::cast(backing) return interpret_cast(node, var_stack) + ast_node::function_call(backing) return interpret_function_call(node, var_stack, enclosing_object) + ast_node::statement(backing) return interpret_statement(node, var_stack, enclosing_object) + ast_node::if_statement(backing) return interpret_if_statement(node, var_stack, enclosing_object) + ast_node::while_loop(backing) return interpret_while_loop(node, var_stack, enclosing_object) + ast_node::for_loop(backing) return interpret_for_loop(node, var_stack, enclosing_object) + ast_node::code_block(backing) return interpret_code_block(node, var_stack, enclosing_object) + ast_node::return_statement(backing) return interpret_return_statement(node, var_stack, enclosing_object) + ast_node::declaration_statement(backing) return interpret_declaration_statement(node, var_stack, enclosing_object) + ast_node::assignment_statement(backing) return interpret_assignment_statement(node, var_stack, enclosing_object) + ast_node::identifier(backing) return interpret_identifier(node, var_stack, enclosing_object) + ast_node::cast(backing) return interpret_cast(node, var_stack, enclosing_object) ast_node::compiler_intrinsic(backing) return interpret_compiler_intrinsic(node, var_stack) ast_node::value(backing) return interpret_value(node) } error(string("Cannot interpret node: ") + get_ast_name(node)) } - 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) - for (var i = 0; i < value_str.length()-1; i++;) { - if (value_str[i] == '\\' && value_str[i+1] == 'n') { - to_ret += '\n' - i++ - } else if (value_str[i] == '\\' && value_str[i+1] == 't') { - to_ret += '\t' - i++ - } else if (i == value_str.length()-2) { - to_ret += value_str[i] - to_ret += value_str[i+1] - } else { - to_ret += value_str[i] - } - } - return value::pointer(make_pair((to_ret.toCharArray()) cast *void, get_ast_type(val))) - } else if (value_str[0] == '\'') //'// lol, comment hack for vim syntax highlighting (my fault, of course) - return value::character(value_str[1]) - else if (value_str == "true") - return value::boolean(true) - else if (value_str == "false") - return value::boolean(false) - else { - // should differentiate between float and double... - var contains_dot = false - for (var i = 0; i < value_str.length(); i++;) { - if (value_str[i] == '.') { - contains_dot = true - break - } - } - if (contains_dot) - if (value_str[value_str.length()-1] == 'f') - return value::floating((string_to_double(value_str.slice(0,-2))) cast float) - else - return value::double_precision(string_to_double(value_str)) - else - return value::integer(string_to_int(value_str)) - } - error("Could not wrap value") - return value::void_nothing() - } }