Refactored interpreter into just functions, added a REPL to the main kraken.

This commit is contained in:
Nathan Braswell
2016-07-03 15:32:45 -07:00
parent 87c2b1d2c1
commit 6fee942756
8 changed files with 846 additions and 896 deletions

View File

@@ -16,19 +16,32 @@ import c_line_control:*
import c_generator:* import c_generator:*
import compiler_version import compiler_version
fun main(argc: int, argv: **char):int { fun main(argc: int, argv: **char):int {
// delay construction until we either load it or copy construct it
var gram: grammer
var base_dir = string("/").join(string(argv[0]).split('/').slice(0,-2))
var file_name = base_dir + "/krakenGrammer.kgm"
var compiled_name = file_name + string(".comp_new")
var compiled_version = 1
var file_contents = read_file(file_name)
var loaded_and_valid = false
var doing_repl = false
if (argc <= 1) { if (argc <= 1) {
error("No input file!\n Call with one argument (the input file), or two arguments (input file and output name)") println("No input file!\n Call with one argument (the input file), or two arguments (input file and output name)\n Falling into REPL...")
compiled_name += ".expr"
file_contents = string("RealGoal = boolean_expression ;\n") + file_contents
doing_repl = true
} else if (string(argv[1]) == "-v" || string(argv[1]) == "--version") { } else if (string(argv[1]) == "-v" || string(argv[1]) == "--version") {
println(compiler_version::version_string) println(compiler_version::version_string)
exit(0) exit(0)
} }
var input_file_offset = 1 var input_file_offset = 1
var interpret_instead = false var interpret_instead = false
var argv1_str = string(argv[1])
var opt_str = string("-O3") var opt_str = string("-O3")
var line_ctrl = false var line_ctrl = false
if (!doing_repl) {
var argv1_str = string(argv[1])
if (argv1_str == "-i") { if (argv1_str == "-i") {
interpret_instead = true interpret_instead = true
input_file_offset++ input_file_offset++
@@ -39,31 +52,17 @@ fun main(argc: int, argv: **char):int {
line_ctrl = true line_ctrl = true
input_file_offset++ input_file_offset++
} }
var kraken_file_name = string(argv[input_file_offset]) }
var executable_name = string(".").join(kraken_file_name.split('.').slice(0,-2))
if (argc == input_file_offset+2)
executable_name = string(argv[input_file_offset+1])
// delay construction until we either load it or copy construct it
var gram: grammer
var base_dir = string("/").join(string(argv[0]).split('/').slice(0,-2))
var file_name = base_dir + "/krakenGrammer.kgm"
var compiled_name = file_name + string(".comp_new")
var compiled_version = 1
var file_contents = read_file(file_name)
var loaded_and_valid = false
if (file_exists(compiled_name)) { if (file_exists(compiled_name)) {
/*println("cached file exists")*/
var pos = 0 var pos = 0
var binary = read_file_binary(compiled_name) var binary = read_file_binary(compiled_name)
/*println("read file!")*/
var saved_version = 0 var saved_version = 0
unpack(saved_version, pos) = unserialize<int>(binary, pos) unpack(saved_version, pos) = unserialize<int>(binary, pos)
if (saved_version == compiled_version) { if (saved_version == compiled_version) {
var cached_contents = string() var cached_contents = string()
unpack(cached_contents, pos) = unserialize<string>(binary, pos) unpack(cached_contents, pos) = unserialize<string>(binary, pos)
if (cached_contents == file_contents) { if (cached_contents == file_contents) {
/*println("loaded_and_valid, using cached version!")*/
loaded_and_valid = true loaded_and_valid = true
pos = gram.unserialize(binary, pos) pos = gram.unserialize(binary, pos)
} else println("contents different") } else println("contents different")
@@ -73,7 +72,6 @@ fun main(argc: int, argv: **char):int {
} }
if (!loaded_and_valid) { if (!loaded_and_valid) {
println("Not loaded_and_valid, re-generating and writing out") println("Not loaded_and_valid, re-generating and writing out")
/*gram = load_grammer(file_contents)*/
// since we now don't construct before hand // since we now don't construct before hand
gram.copy_construct(&load_grammer(file_contents)) gram.copy_construct(&load_grammer(file_contents))
println("grammer loaded, calculate_first_set") println("grammer loaded, calculate_first_set")
@@ -98,6 +96,22 @@ fun main(argc: int, argv: **char):int {
/*var parsers = vector(parse1,parse2,parse3,parse4)*/ /*var parsers = vector(parse1,parse2,parse3,parse4)*/
/*var parsers = vector(parse1,parse2,parse3,parse4,parse5,parse6)*/ /*var parsers = vector(parse1,parse2,parse3,parse4,parse5,parse6)*/
/*var parsers = vector(parse1,parse2,parse3,parse4,parse5,parse6,parse7,parse8)*/ /*var parsers = vector(parse1,parse2,parse3,parse4,parse5,parse6,parse7,parse8)*/
// This is our REPL loop
var scope = ast_translation_unit_ptr(string("stdin"))
while (doing_repl) {
var line = get_line(string("> "), 100)
if (line == "end")
return 0
var trimmed_parse = trim(parse1.parse_input(line, string("stdin")))
var ast_expression = ast_pass.transform_expression(trimmed_parse, scope, map<string, *type>())
print_value(evaluate_constant_expression(ast_expression))
}
var kraken_file_name = string(argv[input_file_offset])
var executable_name = string(".").join(kraken_file_name.split('.').slice(0,-2))
if (argc == input_file_offset+2)
executable_name = string(argv[input_file_offset+1])
var importer.construct(parsers, ast_pass, vector(string(), base_dir + "/stdlib/")): importer var importer.construct(parsers, ast_pass, vector(string(), base_dir + "/stdlib/")): importer
importer.import(kraken_file_name) importer.import(kraken_file_name)
// Passes // Passes
@@ -109,8 +123,7 @@ fun main(argc: int, argv: **char):int {
defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
if (interpret_instead) { if (interpret_instead) {
printlnerr("Interpreting!") printlnerr("Interpreting!")
var interpret.construct(importer.name_ast_map, importer.ast_pass.ast_to_syntax): interpreter call_main(importer.name_ast_map)
interpret.call_main()
} else { } else {
if (line_ctrl) { if (line_ctrl) {
printlnerr("running C-specific passes") printlnerr("running C-specific passes")
@@ -122,7 +135,6 @@ fun main(argc: int, argv: **char):int {
var c_output_pair = c_generator.generate_c(importer.name_ast_map, importer.ast_pass.ast_to_syntax) var c_output_pair = c_generator.generate_c(importer.name_ast_map, importer.ast_pass.ast_to_syntax)
var kraken_c_output_name = kraken_file_name + ".c" var kraken_c_output_name = kraken_file_name + ".c"
write_file(kraken_c_output_name, c_output_pair.first) write_file(kraken_c_output_name, c_output_pair.first)
/*println(string("linker string: ") + c_output_pair.second)*/
var compile_string = "cc -g " + opt_str + " -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -std=c99 " + c_output_pair.second + " " + kraken_c_output_name + " -o " + executable_name var compile_string = "cc -g " + opt_str + " -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -std=c99 " + c_output_pair.second + " " + kraken_c_output_name + " -o " + executable_name
printlnerr(compile_string) printlnerr(compile_string)
system(compile_string) system(compile_string)

View File

@@ -11,6 +11,7 @@ import os:*
import importer:* import importer:*
import ast_nodes:* import ast_nodes:*
import type:* import type:*
import pass_common:*
adt search_type { adt search_type {
none, none,
@@ -1116,74 +1117,6 @@ obj ast_transformation (Object) {
return fitting_functions.max(fun(a: pair<*ast_node, int>, b: pair<*ast_node, int>): bool return a.second < b.second;).first return fitting_functions.max(fun(a: pair<*ast_node, int>, b: pair<*ast_node, int>): bool return a.second < b.second;).first
} }
} }
fun get_from_scope(node: *ast_node, member: *char): *ast_node
return get_from_scope(node, string(member))
fun get_from_scope(node: *ast_node, member: string): *ast_node
return get_ast_scope(node)->get(member).first()
fun has_method(object: *ast_node, name: *char, parameter_types: vector<*type>): bool return has_method(object, string(name), parameter_types);
fun has_method(object: *ast_node, name: string, parameter_types: vector<*type>): bool {
/*println("HAS METHOD:")*/
var to_ret = function_lookup(name, object, parameter_types) || false
/*println("HAS METHOD result:")*/
/*println(to_ret)*/
return to_ret
}
fun make_method_call(object_ident: *ast_node, name: *char, parameters: vector<*ast_node>): *ast_node return make_method_call(object_ident, string(name), parameters);
fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*ast_node>): *ast_node {
/*println("MAKE METHOD CALL OUT:")*/
// note that this type_def is the adt_def if this is an adt type
var method = function_lookup(name, get_ast_type(object_ident)->type_def, parameters.map(fun(param: *ast_node): *type return get_ast_type(param);))
/*print("Here is the Method: ")*/
/*println(method)*/
return make_method_call(object_ident, method, parameters)
}
fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node {
/*println("MAKE METHOD CALL IN:")*/
var access_op = "."
if (get_ast_type(object_ident)->indirection)
access_op = "->"
var method_access = ast_function_call_ptr(get_builtin_function(string(access_op), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method))
return ast_function_call_ptr(method_access, parameters)
}
fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params);
fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node {
return ast_function_call_ptr(get_builtin_function(func, params.map(fun(p:*ast_node): *type return get_ast_type(p);)), params)
}
fun get_builtin_function(name: *char, param_types: vector<*type>): *ast_node
return get_builtin_function(string(name), param_types, null<tree<symbol>>())
fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node
return get_builtin_function(name, param_types, null<tree<symbol>>())
fun get_builtin_function(name: string, param_types: vector<*type>, syntax: *tree<symbol>): *ast_node {
// none of the builtin functions should take in references
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 == "->") {
if (name == "->" && param_types[0]->indirection == 0)
error(syntax, string("drereferencing not a pointer: ") + name)
else if (name == "." && param_types[0]->indirection != 0)
error(syntax, string("dot operator on 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(syntax, 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) {
if (param_types[0]->indirection == 0)
error(syntax, 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)
}
fun unify_type(template_type: *tree<symbol>, param_type: *type, new_map: *map<string, *type>, template_replacements: map<string, *type>) { fun unify_type(template_type: *tree<symbol>, param_type: *type, new_map: *map<string, *type>, template_replacements: map<string, *type>) {
/*println(string("Unifying type: ") + concat_symbol_tree(template_type))*/ /*println(string("Unifying type: ") + concat_symbol_tree(template_type))*/
// first get rid of the reference if we have it - we don't care for unification // first get rid of the reference if we have it - we don't care for unification
@@ -1247,163 +1180,3 @@ fun unify_type(template_type: *tree<symbol>, param_type: *type, new_map: *map<st
error(template_type, "TYPE INFERENCE NOT GOOD ENOUGH") error(template_type, "TYPE INFERENCE NOT GOOD ENOUGH")
} }
} }
fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool {
var func_type = get_ast_type(node)
var func_param_types = func_type->parameter_types
var param_string = string()
param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";)
if (!func_type->is_variadic && func_param_types.size != param_types.size) {
/*println(string("type sizes don't match ") + param_types.size + " with needed " + param_string)*/
return false
} else if (param_types.size < func_param_types.size) {
return false
}
// note we iterate over the func_param_types which will stop short if function is variadic
// just like we want
for (var j = 0; j < func_param_types.size; j++;) {
// don't care about references
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(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
}
}
return true
}
fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node {
/*println(string("doing function lookup for: ") + name)*/
var results = scope_lookup(name, scope)
/*print(results.size); println(" number of results")*/
for (var i = 0; i < results.size; i++;) {
if ((is_function(results[i]) || (is_identifier(results[i]) && get_ast_type(results[i])->is_function())) && function_satisfies_params(results[i], param_types)) {
return results[i]
}
}
/*println(string("function lookup failed for ") + name)*/
return null<ast_node>()
}
fun identifier_lookup(name: ref string, scope: *ast_node): *ast_node {
/*println(string("doing identifier lookup for: ") + name)*/
var results = scope_lookup(name, scope)
if (!results.size) {
/*println(string("identifier lookup failed for ") + name)*/
return null<ast_node>()
}
return results[0]
}
fun scope_lookup(name: ref string, scope: *ast_node): vector<*ast_node> {
// println("*****Doing a name lookup for*****")
// println(name)
var results = vector(scope)
name.split("::").for_each(fun(i: string) {
// println(string("based on split, looking up: ") + i)
var next_results = vector<*ast_node>()
results.for_each(fun(s: *ast_node) {
// print("looking in scope: ")
// println(s)
scope_lookup_helper(i, s, set<*ast_node>()).for_each(fun (result: *ast_node) {
if (!next_results.contains(result))
next_results.add(result)
})
})
results = next_results
})
return results
}
fun scope_lookup_helper(name: ref string, scope: *ast_node, visited: set<*ast_node>): vector<*ast_node> {
// need to do properly scopded lookups
// print("scope is: ")
// get_ast_scope(scope)->for_each(fun(key: string, value: vector<*ast_node>) print(key + " ");)
// println()
var results = vector<*ast_node>()
// prevent re-checking the same one...
if (visited.contains(scope))
return results
visited.add(scope)
if (get_ast_scope(scope)->contains_key(name)) {
// println(name + " is in scope, adding to results")
results += get_ast_scope(scope)->get(name)
}
if (get_ast_scope(scope)->contains_key(string("~enclosing_scope")))
results += scope_lookup_helper(name, get_ast_scope(scope)->get(string("~enclosing_scope"))[0], visited)
if (is_translation_unit(scope)) {
scope->translation_unit.children.for_each(fun(child: *ast_node) {
if (is_import(child)) {
if (child->import.imported.contains(name)) {
// println(name + " is indeed imported")
results += scope_lookup_helper(name, child->import.translation_unit, visited)
} else if (child->import.starred) {
// println("import has an import *, checking along it")
results += scope_lookup_helper(name, child->import.translation_unit, visited)
} else {
// println(name + " is not imported (this time)")
// print("import imports")
// child->import.imported.for_each(fun(it: string) print(it + " ");)
}
}
})
}
return results
}
fun concat_symbol_tree(node: *tree<symbol>): string {
var str.construct(): string
if (node->data.data != "no_value")
str += node->data.data
node->children.for_each(fun(child: *tree<symbol>) str += concat_symbol_tree(child);)
return str
}
fun get_node(lookup: *char, parent: *tree<symbol>): *tree<symbol> {
return get_node(string(lookup), parent)
}
fun get_node(lookup: string, parent: *tree<symbol>): *tree<symbol> {
var results = get_nodes(lookup, parent)
if (results.size > 1)
error(parent, "get node too many results!")
if (results.size)
return results[0]
return null<tree<symbol>>()
}
fun get_nodes(lookup: *char, parent: *tree<symbol>): vector<*tree<symbol>> {
return get_nodes(string(lookup), parent)
}
fun get_nodes(lookup: string, parent: *tree<symbol>): vector<*tree<symbol>> {
return parent->children.filter(fun(node: *tree<symbol>):bool return node->data.name == lookup;)
}
fun add_to_scope(name: *char, to_add: *ast_node, add_to: *ast_node) {
add_to_scope(string(name), to_add, add_to)
}
fun add_to_scope(name: string, to_add: *ast_node, add_to: *ast_node) {
var add_to_map = get_ast_scope(add_to)
if (add_to_map->contains_key(name))
(*add_to_map)[name].add(to_add)
else
add_to_map->set(name, vector(to_add))
}
fun get_first_terminal(source: *tree<symbol>): *tree<symbol> {
if (!source)
return null<tree<symbol>>()
if (source->data.terminal)
return source
if (source->children.size == 0)
return null<tree<symbol>>()
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(source: *tree<symbol>, message: *char) error(source, string(message));
fun error(source: *tree<symbol>, message: string) {
source = get_first_terminal(source)
if (source)
error(source->data.source + ": " + source->data.position + " " + message)
error(message)
}

View File

@@ -8,7 +8,7 @@ import tree:*
import symbol:* import symbol:*
import ast_nodes:* import ast_nodes:*
// for error with syntax tree // for error with syntax tree
import ast_transformation:* import pass_common:*
import poset:* import poset:*
fun code_triple(): code_triple return code_triple(string(), string(), string()); fun code_triple(): code_triple return code_triple(string(), string(), string());
@@ -72,27 +72,6 @@ obj code_triple (Object) {
return pre+value+post 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
}
fun method_in_object(method: *ast_node, enclosing_object: *ast_node): bool {
var methods = enclosing_object->type_def.methods
for (var i = 0; i < methods.size; i++;) {
if (methods[i] == method || (is_template(methods[i]) && methods[i]->template.instantiated.contains(method))) {
return true
}
}
return false
}
obj c_generator (Object) { obj c_generator (Object) {
var id_counter: int var id_counter: int
var ast_to_syntax: map<*ast_node, *tree<symbol>> var ast_to_syntax: map<*ast_node, *tree<symbol>>

View File

@@ -104,7 +104,9 @@ obj importer (Object) {
printlnerr("**Fourth Pass**") printlnerr("**Fourth Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);) name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);)
} }
fun trim(parse_tree: *tree<symbol>) { }
fun trim(parse_tree: *tree<symbol>): *tree<symbol> {
remove_node(symbol("$NULL$", false), parse_tree) remove_node(symbol("$NULL$", false), parse_tree)
remove_node(symbol("WS", false), parse_tree) remove_node(symbol("WS", false), parse_tree)
// the terminals have " around them, which we have to escape // the terminals have " around them, which we have to escape
@@ -145,6 +147,8 @@ obj importer (Object) {
collapse_node(symbol("template_param_list", false), parse_tree) collapse_node(symbol("template_param_list", false), parse_tree)
collapse_node(symbol("trait_list", false), parse_tree) collapse_node(symbol("trait_list", false), parse_tree)
collapse_node(symbol("dec_type", false), parse_tree) collapse_node(symbol("dec_type", false), parse_tree)
return parse_tree
} }
fun remove_node(remove: symbol, parse_tree: *tree<symbol>) { fun remove_node(remove: symbol, parse_tree: *tree<symbol>) {
var to_process = queue<*tree<symbol>>() var to_process = queue<*tree<symbol>>()
@@ -188,5 +192,3 @@ obj importer (Object) {
} }
} }
} }
}

View File

@@ -1,4 +1,3 @@
import io:*
import mem:* import mem:*
import math:* import math:*
import map:* import map:*
@@ -9,12 +8,10 @@ import tree:*
import symbol:* import symbol:*
import ast_nodes:* import ast_nodes:*
import type:* import type:*
import ast_transformation:* import os:*
// for is_dot_style_method_call // for is_dot_style_method_call
import c_generator:* import pass_common:*
// there is never an object literal/primitive
// they remain wrapped in a variable value
adt value { adt value {
boolean: bool, boolean: bool,
character: char, character: char,
@@ -101,7 +98,6 @@ fun wrap_value(val: *ast_node): value {
else if (value_str == "false") else if (value_str == "false")
return value::boolean(false) return value::boolean(false)
else { else {
// should differentiate between float and double...
var contains_dot = false var contains_dot = false
for (var i = 0; i < value_str.length(); i++;) { for (var i = 0; i < value_str.length(); i++;) {
if (value_str[i] == '.') { if (value_str[i] == '.') {
@@ -208,9 +204,9 @@ fun do_basic_op(func_name: string, a: value, b: value): value {
} else if (func_name == "-") { } else if (func_name == "-") {
ptr = ((av.first) cast *char - inc_in_bytes) cast *void ptr = ((av.first) cast *char - inc_in_bytes) cast *void
} else { } else {
println(string("pointer arithmatic is not + or -: ") + func_name + ", b is: ") println(string("pointer arithmatic is not +, -, or ==: ") + func_name + ", b is: ")
print_value(b) print_value(b)
error(string("pointer arithmatic is not + or -: ") + func_name) error(string("pointer arithmatic is not +, -, or ==: ") + func_name)
} }
return value::pointer(make_pair(ptr, av.second)) return value::pointer(make_pair(ptr, av.second))
} }
@@ -336,7 +332,6 @@ fun get_real_value(v: value): value {
if (var_type->indirection) if (var_type->indirection)
return value::pointer(make_pair(*(var_ptr) cast **void, var_type)) return value::pointer(make_pair(*(var_ptr) cast **void, var_type))
match (var_type->base) { match (var_type->base) {
// really this could just be make_pair(variable)
base_type::object() return value::object_like(make_pair(var_ptr, var_type)) base_type::object() return value::object_like(make_pair(var_ptr, var_type))
base_type::boolean() return value::boolean(*(var_ptr) cast *bool) base_type::boolean() return value::boolean(*(var_ptr) cast *bool)
base_type::character() return value::character(*(var_ptr) cast *char) base_type::character() return value::character(*(var_ptr) cast *char)
@@ -360,9 +355,6 @@ fun wrap_into_variable(v: value): value {
return value::variable(make_pair(v.object_like.first, v.object_like.second)) return value::variable(make_pair(v.object_like.first, v.object_like.second))
var variable_type = get_type_from_primitive_value(v) var variable_type = get_type_from_primitive_value(v)
var to_ret = value::variable(make_pair(malloc(type_size(variable_type)), variable_type)) var to_ret = value::variable(make_pair(malloc(type_size(variable_type)), variable_type))
/*if (is_function(v))*/
/*(to_ret.variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->copy_construct(&v.function)*/
/*else*/
store_into_variable(to_ret, v) store_into_variable(to_ret, v)
return to_ret return to_ret
} }
@@ -408,9 +400,6 @@ fun cast_value(v: value, to_type: *type): value {
} }
match (to_type->base) { match (to_type->base) {
// object_like can't be casted // object_like can't be casted
/*base_type::object() return #sizeof<>*/
/*base_type::adt() return #sizeof<>*/
/*base_type::function() return #sizeof<>*/
base_type::boolean() return cast_value_second_half<bool>(v) base_type::boolean() return cast_value_second_half<bool>(v)
base_type::character() return cast_value_second_half<char>(v) base_type::character() return cast_value_second_half<char>(v)
base_type::ucharacter() return cast_value_second_half<uchar>(v) base_type::ucharacter() return cast_value_second_half<uchar>(v)
@@ -510,71 +499,38 @@ fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong {
size += type_size(struct_type->type_def->type_def.variables[i]->declaration_statement.identifier->identifier.type) size += type_size(struct_type->type_def->type_def.variables[i]->declaration_statement.identifier->identifier.type)
return size return size
} }
// to dereference, we basically take the pointer's value (maybe going through a variable to get it)
// and re-wrap it up into a variable value (so it can be assigned to, etc)
fun dereference_pointer_into_variable(dereference_val: value): value fun dereference_pointer_into_variable(dereference_val: value): value
return value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection())) return value::variable(make_pair(get_real_value(dereference_val).pointer.first, dereference_val.pointer.second->clone_with_decreased_indirection()))
fun pop_and_free(var_stack: *stack<map<*ast_node, value>>) { fun pop_and_free(var_stack: *stack<map<*ast_node, value>>) {
var_stack->pop().for_each(fun(k: *ast_node, v: value) { var_stack->pop().for_each(fun(k: *ast_node, v: value) {
match(v) { match(v) {
value::variable(backing) { value::variable(backing) {
/*if (backing.second->is_function())*/
/*(backing.first) cast *pair<*ast_node,map<*ast_node,value>> ->destruct()*/
/*free(backing.first)*/ /*free(backing.first)*/
} }
} }
}) })
} }
obj interpreter (Object) { fun call_main(name_ast_map: ref map<string, pair<*tree<symbol>,*ast_node>>) {
var ast_to_syntax: map<*ast_node, *tree<symbol>>
var name_ast_map: map<string, pair<*tree<symbol>,*ast_node>>
var globals: map<*ast_node, value>
var id_counter: int
fun get_id(): string return to_string(id_counter++);
fun construct(name_ast_map_in: map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax_in: map<*ast_node, *tree<symbol>>): *interpreter {
name_ast_map.copy_construct(&name_ast_map_in)
ast_to_syntax.copy_construct(&ast_to_syntax_in)
globals.construct()
id_counter = 0
return this
}
fun operator=(old: ref interpreter) {
destruct()
copy_construct(&old)
}
fun copy_construct(old: *interpreter) {
name_ast_map.copy_construct(&old->name_ast_map)
ast_to_syntax.copy_construct(&old->ast_to_syntax)
globals.copy_construct(&old->globals)
id_counter == old->id_counter
}
fun destruct() {
name_ast_map.destruct()
ast_to_syntax.destruct()
globals.destruct()
}
fun call_main() {
var results = vector<*ast_node>() var results = vector<*ast_node>()
name_ast_map.for_each(fun(key: string, value: pair<*tree<symbol>,*ast_node>) { name_ast_map.for_each(fun(key: string, value: pair<*tree<symbol>,*ast_node>) {
results += scope_lookup(string("main"), value.second) results += scope_lookup(string("main"), value.second)
}) })
if (results.size != 1) if (results.size != 1)
error(string("wrong number of mains to call: ") + results.size) error(string("wrong number of mains to call: ") + results.size)
printlnerr("=============") var globals = setup_globals(name_ast_map)
printlnerr("setting up globals!")
printlnerr("=============")
setup_globals();
printlnerr("=============")
printlnerr("calling main!")
printlnerr("=============")
var var_stack = stack<map<*ast_node, value>>() var var_stack = stack<map<*ast_node, value>>()
var_stack.push(map<*ast_node,value>()) var_stack.push(map<*ast_node,value>())
var result = call_function(results[0], vector<value>(), vector<*ast_node>(), &var_stack, map<*ast_node,value>(), value::void_nothing(), value::void_nothing(), null<ast_node>()) var result = call_function(results[0], vector<value>(), vector<*ast_node>(), &var_stack, map<*ast_node,value>(), value::void_nothing(), value::void_nothing(), null<ast_node>(), &globals)
printlnerr("=============")
printlnerr("Done!")
printlnerr("=============")
pop_and_free(&var_stack) pop_and_free(&var_stack)
} }
fun setup_globals() { fun evaluate_constant_expression(node: *ast_node): value {
return interpret(node, null<stack<map<*ast_node, value>>>(), value::void_nothing(), null<ast_node>(), null<map<*ast_node, value>>()).first
}
fun setup_globals(name_ast_map: ref map<string, pair<*tree<symbol>,*ast_node>>): map<*ast_node, value> {
var globals = map<*ast_node, value>()
name_ast_map.for_each(fun(key: string, value: pair<*tree<symbol>,*ast_node>) { name_ast_map.for_each(fun(key: string, value: pair<*tree<symbol>,*ast_node>) {
value.second->translation_unit.children.for_each(fun(child: *ast_node) { value.second->translation_unit.children.for_each(fun(child: *ast_node) {
if (is_declaration_statement(child)) { if (is_declaration_statement(child)) {
@@ -586,19 +542,25 @@ obj interpreter (Object) {
var stderr_pointer = malloc(type_size(stderr_type)) var stderr_pointer = malloc(type_size(stderr_type))
*(stderr_pointer) cast **void = stderr; *(stderr_pointer) cast **void = stderr;
globals[declaration.identifier] = value::variable(make_pair(stderr_pointer, stderr_type)) globals[declaration.identifier] = value::variable(make_pair(stderr_pointer, stderr_type))
} else if (identifier.name == "stdin") {
var stdin_type = type_ptr(base_type::void_return(), 1)
var stdin_pointer = malloc(type_size(stdin_type))
*(stdin_pointer) cast **void = stdin;
globals[declaration.identifier] = value::variable(make_pair(stdin_pointer, stdin_type))
} else { } else {
error(string("unknown extern: ") + identifier.name) error(string("unknown extern: ") + identifier.name)
} }
} else { } else {
globals[declaration.identifier] = value::variable(make_pair(calloc(type_size(identifier.type)), identifier.type)) globals[declaration.identifier] = value::variable(make_pair(calloc(type_size(identifier.type)), identifier.type))
if (declaration.expression) if (declaration.expression)
store_into_variable(globals[declaration.identifier], get_real_value(interpret(declaration.expression, null<stack<map<*ast_node,value>>>(), value::void_nothing(), null<ast_node>()).first)) store_into_variable(globals[declaration.identifier], get_real_value(interpret(declaration.expression, null<stack<map<*ast_node,value>>>(), value::void_nothing(), null<ast_node>(), null<map<*ast_node,value>>()).first))
} }
} }
}) })
}) })
return globals
} }
fun interpret_function_call(func_call: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_function_call(func_call: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var func_call_parameters = func_call->function_call.parameters var func_call_parameters = func_call->function_call.parameters
var func_call_func = func_call->function_call.func var func_call_func = func_call->function_call.func
var new_enclosing_object = value::void_nothing() var new_enclosing_object = value::void_nothing()
@@ -606,9 +568,7 @@ obj interpreter (Object) {
var possible_closure_map = map<*ast_node,value>() var possible_closure_map = map<*ast_node,value>()
// test for function value // test for function value
if (!dot_style_method_call && (!is_function(func_call_func) || func_call_func->function.closed_variables.size())) { if (!dot_style_method_call && (!is_function(func_call_func) || func_call_func->function.closed_variables.size())) {
/*error("func_call_func is not a function")*/ var func_value = get_real_value(interpret(func_call_func, var_stack, enclosing_object, enclosing_func, globals).first)
/*println(string("func_call_func is not a function: ") + get_ast_name(func_call_func))*/
var func_value = get_real_value(interpret(func_call_func, var_stack, enclosing_object, enclosing_func).first)
func_call_func = func_value.function.first func_call_func = func_value.function.first
possible_closure_map = *func_value.function.second possible_closure_map = *func_value.function.second
// if the closure closes over this, put it as the enclosing object inside the closure // if the closure closes over this, put it as the enclosing object inside the closure
@@ -617,15 +577,10 @@ obj interpreter (Object) {
new_enclosing_object = get_real_value(dereference_pointer_into_variable(v)) new_enclosing_object = get_real_value(dereference_pointer_into_variable(v))
} }
}) })
/*println("possible_closure_map is")*/
/*possible_closure_map.for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");)*/
/*println()*/
/*println("end pcm")*/
/*println(string("calling func we got from interpreting: ") + get_ast_name(func_call_func))*/
} }
// note here also that this is likely not a foolproof method // note here also that this is likely not a foolproof method
if (dot_style_method_call) { if (dot_style_method_call) {
new_enclosing_object = get_real_value(interpret(func_call_func->function_call.parameters[0], var_stack, enclosing_object, enclosing_func).first) new_enclosing_object = get_real_value(interpret(func_call_func->function_call.parameters[0], var_stack, enclosing_object, enclosing_func, globals).first)
// do a dereference // do a dereference
if (is_pointer(new_enclosing_object)) 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()))) new_enclosing_object = get_real_value(value::variable(make_pair(new_enclosing_object.pointer.first, new_enclosing_object.pointer.second->clone_with_decreased_indirection())))
@@ -642,7 +597,7 @@ obj interpreter (Object) {
if (func_name == "&&" || func_name == "||") { if (func_name == "&&" || func_name == "||") {
error("short circuit still in interpreter") error("short circuit still in interpreter")
} else if (func_name == "." || func_name == "->") { } else if (func_name == "." || func_name == "->") {
var left_side = get_real_value(interpret(func_call_parameters[0], var_stack, enclosing_object, enclosing_func).first) var left_side = get_real_value(interpret(func_call_parameters[0], var_stack, enclosing_object, enclosing_func, globals).first)
var ret_ptr = null<void>() var ret_ptr = null<void>()
if (func_name == "->") if (func_name == "->")
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 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
@@ -656,7 +611,7 @@ obj interpreter (Object) {
var parameter_sources = vector<*ast_node>() var parameter_sources = vector<*ast_node>()
// if we don't have to copy_construct params (is an operator, or has no object params) // if we don't have to copy_construct params (is an operator, or has no object params)
if (func_name == "&" || !func_call_parameters.any_true(fun(p: *ast_node): bool return get_ast_type(p)->is_object() && get_ast_type(p)->indirection == 0;)) { if (func_name == "&" || !func_call_parameters.any_true(fun(p: *ast_node): bool return get_ast_type(p)->is_object() && get_ast_type(p)->indirection == 0;)) {
parameters = func_call_parameters.map(fun(p: *ast_node): value return interpret(p, var_stack, enclosing_object, enclosing_func).first;) parameters = func_call_parameters.map(fun(p: *ast_node): value return interpret(p, var_stack, enclosing_object, enclosing_func, globals).first;)
if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/"
|| func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">=" || func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">="
|| func_name == "==" || func_name == "!=" || func_name == "%" || func_name == "^" || func_name == "==" || func_name == "!=" || func_name == "%" || func_name == "^"
@@ -688,8 +643,6 @@ obj interpreter (Object) {
error("Trying to take address of not a variable or object_like") error("Trying to take address of not a variable or object_like")
} }
} }
// to dereference, we basically take the pointer's value (maybe going through a variable to get it)
// and re-wrap it up into a variable value (so it can be assigned to, etc)
if (func_name == "*" || func_name == "[]") { if (func_name == "*" || func_name == "[]") {
var dereference_val = parameters[0] var dereference_val = parameters[0]
if (func_name == "[]") if (func_name == "[]")
@@ -707,12 +660,12 @@ obj interpreter (Object) {
// not the operator & and at least one object like parameter // not the operator & and at least one object like parameter
parameter_sources = func_call_parameters parameter_sources = func_call_parameters
} }
return make_pair(call_function(func_call_func, parameters, parameter_sources, var_stack, possible_closure_map, enclosing_object, new_enclosing_object, enclosing_func), control_flow::nor()) return make_pair(call_function(func_call_func, parameters, parameter_sources, var_stack, possible_closure_map, enclosing_object, new_enclosing_object, enclosing_func, globals), control_flow::nor())
} }
// call_function can be called with either parameter values in parameters or ast expressions in parameter_sources // call_function can be called with either parameter values in parameters or ast expressions in parameter_sources
// this is to allow easy function calling if we already have the values (for main, say, or to make our job if it's not // this is to allow easy function calling if we already have the values (for main, say, or to make our job if it's not
// an operator easier), but we need to be able to be called with ast_expressions too so we can properly copy_construct once // an operator easier), but we need to be able to be called with ast_expressions too so we can properly copy_construct once
fun call_function(func: *ast_node, parameters: vector<value>, parameter_sources: vector<*ast_node>, var_stack: *stack<map<*ast_node, value>>, possible_closure_map: ref map<*ast_node, value>, enclosing_object: value, new_enclosing_object: value, enclosing_func: *ast_node): value { fun call_function(func: *ast_node, parameters: vector<value>, parameter_sources: vector<*ast_node>, var_stack: *stack<map<*ast_node, value>>, possible_closure_map: ref map<*ast_node, value>, enclosing_object: value, new_enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): value {
// will need adjustment // will need adjustment
if (!is_function(func)) if (!is_function(func))
error("Can't handle not function function calls (can do regular method, is this chained or something?)") error("Can't handle not function function calls (can do regular method, is this chained or something?)")
@@ -721,13 +674,6 @@ obj interpreter (Object) {
// start out with the possible closure map as the highest scope (gloabals checked seperately) // start out with the possible closure map as the highest scope (gloabals checked seperately)
var new_var_stack = stack(possible_closure_map) var new_var_stack = stack(possible_closure_map)
new_var_stack.push(map<*ast_node,value>()) new_var_stack.push(map<*ast_node,value>())
/*println("stack after pcm and new m is")*/
/*for (var i = 0; i < new_var_stack.size(); i++;) {*/
/*println(string("level: ") + i)*/
/*new_var_stack.from_top(i).for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");)*/
/*println()*/
/*}*/
/*println("end stack after")*/
// if this is a value based call, pull from parameters // if this is a value based call, pull from parameters
if (parameter_sources.size == 0) { if (parameter_sources.size == 0) {
/*println(func_name + " being called with parameter values")*/ /*println(func_name + " being called with parameter values")*/
@@ -743,9 +689,6 @@ obj interpreter (Object) {
new_var_stack.top()[param_ident] = wrap_into_variable(parameters[i]) new_var_stack.top()[param_ident] = wrap_into_variable(parameters[i])
} else { } else {
new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
//HERE
/*if (param_type->indirection == 0 && param_type->is_function())*/
/*(new_var_stack.top()[param_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct()*/
store_into_variable(new_var_stack.top()[param_ident], get_real_value(parameters[i])) store_into_variable(new_var_stack.top()[param_ident], get_real_value(parameters[i]))
} }
} }
@@ -760,18 +703,18 @@ obj interpreter (Object) {
var param_type = get_ast_type(func)->parameter_types[i] var param_type = get_ast_type(func)->parameter_types[i]
var param_ident = func->function.parameters[i] var param_ident = func->function.parameters[i]
if (param_type->is_ref) { if (param_type->is_ref) {
var param = interpret(parameter_sources[i], var_stack, enclosing_object, enclosing_func).first var param = interpret(parameter_sources[i], var_stack, enclosing_object, enclosing_func, globals).first
if (is_variable(param)) if (is_variable(param))
new_var_stack.top()[param_ident] = param new_var_stack.top()[param_ident] = param
else else
new_var_stack.top()[param_ident] = wrap_into_variable(param) new_var_stack.top()[param_ident] = wrap_into_variable(param)
} else { } else {
new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type))
store_into_variable(new_var_stack.top()[param_ident], get_real_value(interpret(parameter_sources[i], var_stack, enclosing_object, enclosing_func).first)) store_into_variable(new_var_stack.top()[param_ident], get_real_value(interpret(parameter_sources[i], var_stack, enclosing_object, enclosing_func, globals).first))
} }
} }
} }
var to_ret = interpret(func->function.body_statement, &new_var_stack, new_enclosing_object, func).first var to_ret = interpret(func->function.body_statement, &new_var_stack, new_enclosing_object, func, globals).first
// to_ret is on the new_var_stack, likely // to_ret is on the new_var_stack, likely
/*pop_and_free(&new_var_stack)*/ /*pop_and_free(&new_var_stack)*/
if (parameter_sources.size) { if (parameter_sources.size) {
@@ -849,39 +792,33 @@ obj interpreter (Object) {
} }
return value::void_nothing() return value::void_nothing()
} }
fun interpret_function(function: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_function(function: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var possible_closure_map = new<map<*ast_node,value>>()->construct() var possible_closure_map = new<map<*ast_node,value>>()->construct()
/*println("trying to close")*/
function->function.closed_variables.for_each(fun(v: *ast_node) { function->function.closed_variables.for_each(fun(v: *ast_node) {
(*possible_closure_map)[v] = interpret_identifier(v, var_stack, enclosing_object, enclosing_func).first (*possible_closure_map)[v] = interpret_identifier(v, var_stack, enclosing_object, enclosing_func, globals).first
/*println(string("closed over ") + get_ast_name(v))*/
}) })
/*println("in interpret function possible_closure_map is")*/
/*possible_closure_map->for_each(fun(key: *ast_node, v: value) print(get_ast_name(key) + " ");)*/
/*println()*/
/*println("end in inteprret function pcm")*/
return make_pair(value::function(make_pair(function, possible_closure_map)), control_flow::nor()) return make_pair(value::function(make_pair(function, possible_closure_map)), control_flow::nor())
} }
fun interpret_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
return interpret(stmt->statement.child, var_stack, enclosing_object, enclosing_func) return interpret(stmt->statement.child, var_stack, enclosing_object, enclosing_func, globals)
} }
fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var_stack->push(map<*ast_node,value>()) var_stack->push(map<*ast_node,value>())
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) 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).first)) { if (truthy(interpret(if_stmt->if_statement.condition, var_stack, enclosing_object, enclosing_func, globals).first)) {
value_from_inside = interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object, enclosing_func) value_from_inside = interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object, enclosing_func, globals)
} else if (if_stmt->if_statement.else_part) { } else if (if_stmt->if_statement.else_part) {
value_from_inside = interpret(if_stmt->if_statement.else_part, var_stack, enclosing_object, enclosing_func) value_from_inside = interpret(if_stmt->if_statement.else_part, var_stack, enclosing_object, enclosing_func, globals)
} }
pop_and_free(var_stack) pop_and_free(var_stack)
return value_from_inside return value_from_inside
} }
fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var_stack->push(map<*ast_node,value>()) var_stack->push(map<*ast_node,value>())
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
var going = true var going = true
while (going && truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object, enclosing_func).first)) { while (going && truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object, enclosing_func, globals).first)) {
value_from_inside = interpret(while_loop->while_loop.statement, var_stack, enclosing_object, enclosing_func) value_from_inside = interpret(while_loop->while_loop.statement, var_stack, enclosing_object, enclosing_func, globals)
if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre()) if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre())
going = false going = false
if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con()) if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con())
@@ -890,14 +827,14 @@ obj interpreter (Object) {
pop_and_free(var_stack) pop_and_free(var_stack)
return value_from_inside return value_from_inside
} }
fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var_stack->push(map<*ast_node,value>()) var_stack->push(map<*ast_node,value>())
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
var going = true var going = true
if (for_loop->for_loop.init) if (for_loop->for_loop.init)
interpret(for_loop->for_loop.init, var_stack, enclosing_object, enclosing_func) interpret(for_loop->for_loop.init, var_stack, enclosing_object, enclosing_func, globals)
while (going && (!for_loop->for_loop.condition || truthy(interpret(for_loop->for_loop.condition, var_stack, enclosing_object, enclosing_func).first))) { while (going && (!for_loop->for_loop.condition || truthy(interpret(for_loop->for_loop.condition, var_stack, enclosing_object, enclosing_func, globals).first))) {
value_from_inside = interpret(for_loop->for_loop.body, var_stack, enclosing_object, enclosing_func) value_from_inside = interpret(for_loop->for_loop.body, var_stack, enclosing_object, enclosing_func, globals)
if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre()) if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre())
going = false going = false
if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con()) if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con())
@@ -905,7 +842,7 @@ obj interpreter (Object) {
// only run update if we're not breaking or continuing // only run update if we're not breaking or continuing
if (going && for_loop->for_loop.update) if (going && for_loop->for_loop.update)
interpret(for_loop->for_loop.update, var_stack, enclosing_object, enclosing_func) interpret(for_loop->for_loop.update, var_stack, enclosing_object, enclosing_func, globals)
} }
pop_and_free(var_stack) pop_and_free(var_stack)
return value_from_inside return value_from_inside
@@ -917,10 +854,10 @@ obj interpreter (Object) {
} }
error("bad branch type") error("bad branch type")
} }
fun interpret_code_block(block: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_code_block(block: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var_stack->push(map<*ast_node,value>()) var_stack->push(map<*ast_node,value>())
for (var i = 0; i < block->code_block.children.size; i++;) { for (var i = 0; i < block->code_block.children.size; i++;) {
var statement = interpret(block->code_block.children[i], var_stack, enclosing_object, enclosing_func) var statement = interpret(block->code_block.children[i], var_stack, enclosing_object, enclosing_func, globals)
match (statement.second) { match (statement.second) {
control_flow::con() { control_flow::con() {
pop_and_free(var_stack) pop_and_free(var_stack)
@@ -940,39 +877,39 @@ obj interpreter (Object) {
pop_and_free(var_stack) pop_and_free(var_stack)
return make_pair(value::void_nothing(), control_flow::nor()) return make_pair(value::void_nothing(), control_flow::nor())
} }
fun interpret_return_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_return_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
if (stmt->return_statement.return_value == null<ast_node>()) if (stmt->return_statement.return_value == null<ast_node>())
return make_pair(value::void_nothing(), control_flow::ret()) return make_pair(value::void_nothing(), control_flow::ret())
var return_expression = stmt->return_statement.return_value var return_expression = stmt->return_statement.return_value
var return_type = get_ast_type(return_expression) var return_type = get_ast_type(return_expression)
var to_ret.construct(): value var to_ret.construct(): value
if (get_ast_type(enclosing_func)->return_type->is_ref) { if (get_ast_type(enclosing_func)->return_type->is_ref) {
to_ret = interpret(return_expression, var_stack, enclosing_object, enclosing_func).first to_ret = interpret(return_expression, var_stack, enclosing_object, enclosing_func, globals).first
if (!is_variable(to_ret)) { if (!is_variable(to_ret)) {
print("here is: ") print("here is: ")
print_value(to_ret) print_value(to_ret)
error("interpreter returning reference is not variable") error("interpreter returning reference is not variable")
} }
} else { } else {
to_ret = interpret(return_expression, var_stack, enclosing_object, enclosing_func).first to_ret = interpret(return_expression, var_stack, enclosing_object, enclosing_func, globals).first
} }
return make_pair(to_ret, control_flow::ret()) return make_pair(to_ret, control_flow::ret())
} }
fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var ident = stmt->declaration_statement.identifier var ident = stmt->declaration_statement.identifier
var ident_type = ident->identifier.type var ident_type = ident->identifier.type
var_stack->top()[ident] = value::variable(make_pair(malloc(type_size(ident_type)),ident_type)) var_stack->top()[ident] = value::variable(make_pair(malloc(type_size(ident_type)),ident_type))
// NOTE: store_into_variable takes to in as a ref because it might change it in the special case ref = ptr // NOTE: store_into_variable takes to in as a ref because it might change it in the special case ref = ptr
if (stmt->declaration_statement.expression) { if (stmt->declaration_statement.expression) {
store_into_variable(var_stack->top()[ident], get_real_value(interpret(stmt->declaration_statement.expression, var_stack, enclosing_object, enclosing_func).first)) store_into_variable(var_stack->top()[ident], get_real_value(interpret(stmt->declaration_statement.expression, var_stack, enclosing_object, enclosing_func, globals).first))
} else if (stmt->declaration_statement.init_method_call) { } else if (stmt->declaration_statement.init_method_call) {
interpret(stmt->declaration_statement.init_method_call, var_stack, enclosing_object, enclosing_func) interpret(stmt->declaration_statement.init_method_call, var_stack, enclosing_object, enclosing_func, globals)
} }
return make_pair(value::void_nothing(), control_flow::nor()) return make_pair(value::void_nothing(), control_flow::nor())
} }
fun interpret_assignment_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_assignment_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
var to = interpret(stmt->assignment_statement.to, var_stack, enclosing_object, enclosing_func).first var to = interpret(stmt->assignment_statement.to, var_stack, enclosing_object, enclosing_func, globals).first
var from = interpret(stmt->assignment_statement.from, var_stack, enclosing_object, enclosing_func).first var from = interpret(stmt->assignment_statement.from, var_stack, enclosing_object, enclosing_func, globals).first
assert(is_variable(to), "assigning into not a variable") assert(is_variable(to), "assigning into not a variable")
// always do cast now to make our best effort at assignment (assign into a double from a float, etc) // always do cast now to make our best effort at assignment (assign into a double from a float, etc)
// unless it's an object // unless it's an object
@@ -984,7 +921,7 @@ obj interpreter (Object) {
store_into_variable(to, cast_value(from_real, to.variable.second)) store_into_variable(to, cast_value(from_real, to.variable.second))
return make_pair(value::void_nothing(), control_flow::nor()) return make_pair(value::void_nothing(), control_flow::nor())
} }
fun interpret_identifier(ident: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_identifier(ident: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
for (var i = 0; i < var_stack->size(); i++;) for (var i = 0; i < var_stack->size(); i++;)
if (var_stack->from_top(i).contains_key(ident)) if (var_stack->from_top(i).contains_key(ident))
return make_pair(var_stack->from_top(i)[ident], control_flow::nor()) return make_pair(var_stack->from_top(i)[ident], control_flow::nor())
@@ -1001,8 +938,8 @@ obj interpreter (Object) {
} }
} }
// check for global // check for global
if (globals.contains_key(ident)) if (globals->contains_key(ident))
return make_pair(globals[ident], control_flow::nor()) return make_pair((*globals)[ident], control_flow::nor())
println("couldn't find it in interpret identifier, scope:") println("couldn't find it in interpret identifier, scope:")
for (var i = 0; i < var_stack->size(); i++;) { for (var i = 0; i < var_stack->size(); i++;) {
println(string("level: ") + i) println(string("level: ") + i)
@@ -1021,8 +958,8 @@ obj interpreter (Object) {
} }
error(string("Cannot find variable: ") + ident->identifier.name) error(string("Cannot find variable: ") + ident->identifier.name)
} }
fun interpret_cast(node: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret_cast(node: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
return make_pair(cast_value(interpret(node->cast.value, var_stack, enclosing_object, enclosing_func).first, node->cast.to_type), control_flow::nor()) return make_pair(cast_value(interpret(node->cast.value, var_stack, enclosing_object, enclosing_func, globals).first, node->cast.to_type), control_flow::nor())
} }
fun interpret_compiler_intrinsic(node: *ast_node, var_stack: *stack<map<*ast_node, value>>): pair<value, control_flow> { fun interpret_compiler_intrinsic(node: *ast_node, var_stack: *stack<map<*ast_node, value>>): pair<value, control_flow> {
var intrinsic_name = node->compiler_intrinsic.intrinsic var intrinsic_name = node->compiler_intrinsic.intrinsic
@@ -1032,26 +969,25 @@ obj interpreter (Object) {
} }
fun interpret_value(val: *ast_node): pair<value, control_flow> fun interpret_value(val: *ast_node): pair<value, control_flow>
return make_pair(wrap_value(val), control_flow::nor()) return make_pair(wrap_value(val), control_flow::nor())
fun interpret(node: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node): pair<value, control_flow> { fun interpret(node: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, globals: *map<*ast_node, value>): pair<value, control_flow> {
if (!node) error("cannot interpret null node!") if (!node) error("cannot interpret null node!")
match (*node) { match (*node) {
ast_node::function_call(backing) return interpret_function_call(node, var_stack, enclosing_object, enclosing_func) ast_node::function_call(backing) return interpret_function_call(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::function(backing) return interpret_function(node, var_stack, enclosing_object, enclosing_func) ast_node::function(backing) return interpret_function(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::statement(backing) return interpret_statement(node, var_stack, enclosing_object, enclosing_func) ast_node::statement(backing) return interpret_statement(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::if_statement(backing) return interpret_if_statement(node, var_stack, enclosing_object, enclosing_func) ast_node::if_statement(backing) return interpret_if_statement(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::while_loop(backing) return interpret_while_loop(node, var_stack, enclosing_object, enclosing_func) ast_node::while_loop(backing) return interpret_while_loop(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::for_loop(backing) return interpret_for_loop(node, var_stack, enclosing_object, enclosing_func) ast_node::for_loop(backing) return interpret_for_loop(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::branching_statement(backing) return interpret_branching_statement(node) ast_node::branching_statement(backing) return interpret_branching_statement(node)
ast_node::code_block(backing) return interpret_code_block(node, var_stack, enclosing_object, enclosing_func) ast_node::code_block(backing) return interpret_code_block(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::return_statement(backing) return interpret_return_statement(node, var_stack, enclosing_object, enclosing_func) ast_node::return_statement(backing) return interpret_return_statement(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::declaration_statement(backing) return interpret_declaration_statement(node, var_stack, enclosing_object, enclosing_func) ast_node::declaration_statement(backing) return interpret_declaration_statement(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::assignment_statement(backing) return interpret_assignment_statement(node, var_stack, enclosing_object, enclosing_func) ast_node::assignment_statement(backing) return interpret_assignment_statement(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::identifier(backing) return interpret_identifier(node, var_stack, enclosing_object, enclosing_func) ast_node::identifier(backing) return interpret_identifier(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::cast(backing) return interpret_cast(node, var_stack, enclosing_object, enclosing_func) ast_node::cast(backing) return interpret_cast(node, var_stack, enclosing_object, enclosing_func, globals)
ast_node::compiler_intrinsic(backing) return interpret_compiler_intrinsic(node, var_stack) ast_node::compiler_intrinsic(backing) return interpret_compiler_intrinsic(node, var_stack)
ast_node::value(backing) return interpret_value(node) ast_node::value(backing) return interpret_value(node)
} }
error(string("Cannot interpret node: ") + get_ast_name(node)) error(string("Cannot interpret node: ") + get_ast_name(node))
} }
}

View File

@@ -7,7 +7,21 @@ ext fun fprintf(file: *void, format: *char, ...): int
ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int
ext fun fflush(file: int): int ext fun fflush(file: int): int
ext var stderr: *void ext var stderr: *void
ext fun fgets(buff: *char, size: int, file: *void): *char
ext var stdin: *void
// dead simple stdin
fun get_line(prompt: string::string, line_size: int): string::string {
print(prompt)
return get_line(line_size)
}
fun get_line(line_size: int): string::string {
var buff = new<char>(line_size)
fgets(buff, line_size, stdin)
var to_ret = string::string(buff)
delete(buff)
return to_ret.slice(0,-2) // remove '\n'
}
fun printlnerr<T>(toPrint: T) : void { fun printlnerr<T>(toPrint: T) : void {
printerr(toPrint) printerr(toPrint)
printerr("\n") printerr("\n")

View File

@@ -1,5 +1,4 @@
import ast_nodes:* import ast_nodes:*
import ast_transformation:*
import mem:* import mem:*
import util:* import util:*
import vector:* import vector:*
@@ -9,6 +8,200 @@ import string:*
fun make_this_noncached(object: *ast_node): *ast_node { fun make_this_noncached(object: *ast_node): *ast_node {
return ast_identifier_ptr("this", object->type_def.self_type->clone_with_indirection(1), object) return ast_identifier_ptr("this", object->type_def.self_type->clone_with_indirection(1), object)
} }
fun get_first_terminal(source: *tree<symbol>): *tree<symbol> {
if (!source)
return null<tree<symbol>>()
if (source->data.terminal)
return source
if (source->children.size == 0)
return null<tree<symbol>>()
return get_first_terminal(source->children.first())
}
fun error(source: *tree<symbol>, message: *char) error(source, string(message));
fun error(source: *tree<symbol>, message: string) {
source = get_first_terminal(source)
if (source)
error(source->data.source + ": " + source->data.position + " " + message)
error(message)
}
fun method_in_object(method: *ast_node, enclosing_object: *ast_node): bool {
var methods = enclosing_object->type_def.methods
for (var i = 0; i < methods.size; i++;) {
if (methods[i] == method || (is_template(methods[i]) && methods[i]->template.instantiated.contains(method))) {
return true
}
}
return false
}
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
}
fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool {
var func_type = get_ast_type(node)
var func_param_types = func_type->parameter_types
var param_string = string()
param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";)
if (!func_type->is_variadic && func_param_types.size != param_types.size) {
/*println(string("type sizes don't match ") + param_types.size + " with needed " + param_string)*/
return false
} else if (param_types.size < func_param_types.size) {
return false
}
// note we iterate over the func_param_types which will stop short if function is variadic
// just like we want
for (var j = 0; j < func_param_types.size; j++;) {
// don't care about references
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(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
}
}
return true
}
fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node {
var results = scope_lookup(name, scope)
for (var i = 0; i < results.size; i++;) {
if ((is_function(results[i]) || (is_identifier(results[i]) && get_ast_type(results[i])->is_function())) && function_satisfies_params(results[i], param_types)) {
return results[i]
}
}
return null<ast_node>()
}
fun identifier_lookup(name: ref string, scope: *ast_node): *ast_node {
/*println(string("doing identifier lookup for: ") + name)*/
var results = scope_lookup(name, scope)
if (!results.size) {
/*println(string("identifier lookup failed for ") + name)*/
return null<ast_node>()
}
return results[0]
}
fun scope_lookup(name: ref string, scope: *ast_node): vector<*ast_node> {
// println("*****Doing a name lookup for*****")
// println(name)
var results = vector(scope)
name.split("::").for_each(fun(i: string) {
// println(string("based on split, looking up: ") + i)
var next_results = vector<*ast_node>()
results.for_each(fun(s: *ast_node) {
// print("looking in scope: ")
// println(s)
scope_lookup_helper(i, s, set<*ast_node>()).for_each(fun (result: *ast_node) {
if (!next_results.contains(result))
next_results.add(result)
})
})
results = next_results
})
return results
}
fun scope_lookup_helper(name: ref string, scope: *ast_node, visited: set<*ast_node>): vector<*ast_node> {
// need to do properly scopded lookups
// print("scope is: ")
// get_ast_scope(scope)->for_each(fun(key: string, value: vector<*ast_node>) print(key + " ");)
// println()
var results = vector<*ast_node>()
// prevent re-checking the same one...
if (visited.contains(scope))
return results
visited.add(scope)
if (get_ast_scope(scope)->contains_key(name)) {
// println(name + " is in scope, adding to results")
results += get_ast_scope(scope)->get(name)
}
if (get_ast_scope(scope)->contains_key(string("~enclosing_scope")))
results += scope_lookup_helper(name, get_ast_scope(scope)->get(string("~enclosing_scope"))[0], visited)
if (is_translation_unit(scope)) {
scope->translation_unit.children.for_each(fun(child: *ast_node) {
if (is_import(child)) {
if (child->import.imported.contains(name)) {
// println(name + " is indeed imported")
results += scope_lookup_helper(name, child->import.translation_unit, visited)
} else if (child->import.starred) {
// println("import has an import *, checking along it")
results += scope_lookup_helper(name, child->import.translation_unit, visited)
} else {
// println(name + " is not imported (this time)")
// print("import imports")
// child->import.imported.for_each(fun(it: string) print(it + " ");)
}
}
})
}
return results
}
fun has_method(object: *ast_node, name: *char, parameter_types: vector<*type>): bool return has_method(object, string(name), parameter_types);
fun has_method(object: *ast_node, name: string, parameter_types: vector<*type>): bool {
var to_ret = function_lookup(name, object, parameter_types) || false
return to_ret
}
fun get_from_scope(node: *ast_node, member: *char): *ast_node
return get_from_scope(node, string(member))
fun get_from_scope(node: *ast_node, member: string): *ast_node
return get_ast_scope(node)->get(member).first()
fun make_method_call(object_ident: *ast_node, name: *char, parameters: vector<*ast_node>): *ast_node return make_method_call(object_ident, string(name), parameters);
fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*ast_node>): *ast_node {
// note that this type_def is the adt_def if this is an adt type
var method = function_lookup(name, get_ast_type(object_ident)->type_def, parameters.map(fun(param: *ast_node): *type return get_ast_type(param);))
return make_method_call(object_ident, method, parameters)
}
fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node {
var access_op = "."
if (get_ast_type(object_ident)->indirection)
access_op = "->"
var method_access = ast_function_call_ptr(get_builtin_function(string(access_op), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method))
return ast_function_call_ptr(method_access, parameters)
}
fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params);
fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node {
return ast_function_call_ptr(get_builtin_function(func, params.map(fun(p:*ast_node): *type return get_ast_type(p);)), params)
}
fun get_builtin_function(name: *char, param_types: vector<*type>): *ast_node
return get_builtin_function(string(name), param_types, null<tree<symbol>>())
fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node
return get_builtin_function(name, param_types, null<tree<symbol>>())
fun get_builtin_function(name: string, param_types: vector<*type>, syntax: *tree<symbol>): *ast_node {
// none of the builtin functions should take in references
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 == "->") {
if (name == "->" && param_types[0]->indirection == 0)
error(syntax, string("drereferencing not a pointer: ") + name)
else if (name == "." && param_types[0]->indirection != 0)
error(syntax, string("dot operator on 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(syntax, 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) {
if (param_types[0]->indirection == 0)
error(syntax, 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)
}
fun possible_object_equality(lvalue: *ast_node, rvalue: *ast_node): *ast_node { fun possible_object_equality(lvalue: *ast_node, rvalue: *ast_node): *ast_node {
var ltype = get_ast_type(lvalue) var ltype = get_ast_type(lvalue)
var rtype = get_ast_type(rvalue) var rtype = get_ast_type(rvalue)
@@ -19,7 +212,40 @@ fun possible_object_equality(lvalue: *ast_node, rvalue: *ast_node): *ast_node {
return ast_value_ptr(string("false"), type_ptr(base_type::boolean())) return ast_value_ptr(string("false"), type_ptr(base_type::boolean()))
return make_operator_call("==", vector(lvalue, rvalue)) return make_operator_call("==", vector(lvalue, rvalue))
} }
fun concat_symbol_tree(node: *tree<symbol>): string {
var str.construct(): string
if (node->data.data != "no_value")
str += node->data.data
node->children.for_each(fun(child: *tree<symbol>) str += concat_symbol_tree(child);)
return str
}
fun get_node(lookup: *char, parent: *tree<symbol>): *tree<symbol> {
return get_node(string(lookup), parent)
}
fun get_node(lookup: string, parent: *tree<symbol>): *tree<symbol> {
var results = get_nodes(lookup, parent)
if (results.size > 1)
error(parent, "get node too many results!")
if (results.size)
return results[0]
return null<tree<symbol>>()
}
fun get_nodes(lookup: *char, parent: *tree<symbol>): vector<*tree<symbol>> {
return get_nodes(string(lookup), parent)
}
fun get_nodes(lookup: string, parent: *tree<symbol>): vector<*tree<symbol>> {
return parent->children.filter(fun(node: *tree<symbol>):bool return node->data.name == lookup;)
}
fun add_to_scope(name: *char, to_add: *ast_node, add_to: *ast_node) {
add_to_scope(string(name), to_add, add_to)
}
fun add_to_scope(name: string, to_add: *ast_node, add_to: *ast_node) {
var add_to_map = get_ast_scope(add_to)
if (add_to_map->contains_key(name))
(*add_to_map)[name].add(to_add)
else
add_to_map->set(name, vector(to_add))
}
// for now, needs source to already be in a variable for copy_constructing // for now, needs source to already be in a variable for copy_constructing
fun assign_or_copy_construct_statement(lvalue: *ast_node, rvalue: *ast_node): *ast_node { fun assign_or_copy_construct_statement(lvalue: *ast_node, rvalue: *ast_node): *ast_node {
var ltype = get_ast_type(lvalue) var ltype = get_ast_type(lvalue)

View File

@@ -20,6 +20,14 @@ fun error(message: string::string) {
io::printlnerr(message) io::printlnerr(message)
os::exit(-1) os::exit(-1)
} }
fun assert(works: bool, message: *char) {
if (!works)
error(message)
}
fun assert(works: bool, message: string::string) {
if (!works)
error(message)
}
fun deref_equality<T>(a: *T, b: *T): bool { fun deref_equality<T>(a: *T, b: *T): bool {
if ( (a && b && !(*a == *b)) || (a && !b) || (!a && b) ) if ( (a && b && !(*a == *b)) || (a && !b) || (!a && b) )