Basic CTCE working! In between commit because #link(a) syntax changed to #link(a)

This commit is contained in:
Nathan Braswell
2016-07-03 22:50:42 -07:00
parent 6fee942756
commit 0f2ac1421a
17 changed files with 183 additions and 183 deletions

View File

@@ -12,6 +12,7 @@ import ast_transformation:*
import adt_lower:*
import obj_lower:*
import defer_lower:*
import ctce_lower:*
import c_line_control:*
import c_generator:*
import compiler_version
@@ -121,6 +122,8 @@ fun main(argc: int, argv: **char):int {
obj_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
printlnerr("Lowering Defer")
defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
printlnerr("Lowering CTCE")
ctce_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)
if (interpret_instead) {
printlnerr("Interpreting!")
call_main(importer.name_ast_map)

View File

@@ -116,9 +116,7 @@ continue_statement = "continue" ;
defer_statement = "defer" WS statement ;
function_call = unarad WS "\(" WS opt_parameter_list WS "\)" ;
compiler_intrinsic = "#" identifier WS "\(" WS intrinsic_parameter_list WS "\)" | "#" identifier WS "<" WS type_list WS ">" ;
intrinsic_parameter_list = intrinsic_parameter_list WS "," WS intrinsic_parameter | intrinsic_parameter ;
intrinsic_parameter = identifier ;
compiler_intrinsic = "#" identifier WS "\(" WS opt_parameter_list WS "\)" | "#" identifier WS "<" WS type_list WS ">" ;
boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ;
and_boolean_expression = and_boolean_expression WS "&&" WS bitwise_or | bitwise_or ;

View File

@@ -43,19 +43,19 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
node->adt_def.option_funcs.for_each(fun(func: *ast_node) {
var adt_type = replacement->type_def.self_type
var block = ast_code_block_ptr()
func->function.body_statement = ast_statement_ptr(block)
func->function.body_statement = block
var to_ret = ast_identifier_ptr(string("to_ret"), adt_type, block)
block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(to_ret, null<ast_node>(), false)))
block->code_block.children.add(ast_declaration_statement_ptr(to_ret, null<ast_node>(), false))
var value = ast_value_ptr(to_string(idx), type_ptr(base_type::integer()))
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call(".", vector(to_ret, flag)), value)))
block->code_block.children.add(ast_assignment_statement_ptr(make_operator_call(".", vector(to_ret, flag)), value))
var opt = type_def_option_map[node][idx]
var lvalue = make_operator_call(".", vector(make_operator_call(".", vector(to_ret, option_union_ident)), opt))
if (func->function.parameters.size) {
// do copy_construct if it should
block->code_block.children.add(ast_statement_ptr(assign_or_copy_construct_statement(lvalue, func->function.parameters[0])))
block->code_block.children.add(assign_or_copy_construct_statement(lvalue, func->function.parameters[0]))
}
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(to_ret)))
block->code_block.children.add(ast_return_statement_ptr(to_ret))
add_before_in(func, node, parent_chain)
add_to_scope(func->function.name, func, enclosing_scope)
add_to_scope("~enclosing_scope", enclosing_scope, func)
@@ -63,11 +63,11 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
})
node->adt_def.regular_funcs.for_each(fun(func: *ast_node) {
var block = ast_code_block_ptr()
func->function.body_statement = ast_statement_ptr(block)
func->function.body_statement = block
if (func->function.name == "operator==") {
var other = func->function.parameters[0]
var if_stmt = ast_if_statement_ptr(make_operator_call("!=", vector(make_operator_call("->", vector(replacement_this, flag)), make_operator_call(".", vector(other, flag)))))
if_stmt->if_statement.then_part = ast_statement_ptr(ast_return_statement_ptr(ast_value_ptr(string("false"), type_ptr(base_type::boolean()))))
if_stmt->if_statement.then_part = ast_return_statement_ptr(ast_value_ptr(string("false"), type_ptr(base_type::boolean())))
block->code_block.children.add(if_stmt)
for (var i = 0; i < type_def_option_map[node].size; i++;) {
@@ -77,20 +77,20 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
var option = type_def_option_map[node][i]
var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option))
var their_option = make_operator_call(".", vector(make_operator_call(".", vector(other, option_union_ident)), option))
if_stmt_inner->if_statement.then_part = ast_statement_ptr(ast_return_statement_ptr(possible_object_equality(our_option, their_option)))
if_stmt_inner->if_statement.then_part = ast_return_statement_ptr(possible_object_equality(our_option, their_option))
block->code_block.children.add(if_stmt_inner)
}
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(ast_value_ptr(string("true"), type_ptr(base_type::boolean())))))
block->code_block.children.add(ast_return_statement_ptr(ast_value_ptr(string("true"), type_ptr(base_type::boolean()))))
} else if (func->function.name == "operator!=") {
var other = func->function.parameters[0]
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(make_operator_call("!", vector(make_method_call(replacement_this, "operator==", vector(other)))))))
block->code_block.children.add(ast_return_statement_ptr(make_operator_call("!", vector(make_method_call(replacement_this, "operator==", vector(other))))))
} else if (func->function.name == "construct") {
var value = ast_value_ptr(string("-1"), type_ptr(base_type::integer()))
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), value)))
block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(replacement_this)))
block->code_block.children.add(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), value))
block->code_block.children.add(ast_return_statement_ptr(replacement_this))
} else if (func->function.name == "copy_construct") {
var other = func->function.parameters[0]
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), make_operator_call("->", vector(other, flag)))))
block->code_block.children.add(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), make_operator_call("->", vector(other, flag))))
for (var i = 0; i < type_def_option_map[node].size; i++;) {
if (get_ast_type(type_def_option_map[node][i])->is_empty_adt_option())
continue
@@ -98,13 +98,13 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
var option = type_def_option_map[node][i]
var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option))
var their_option = make_operator_call(".", vector(make_operator_call("->", vector(other, option_union_ident)), option))
if_stmt_inner->if_statement.then_part = ast_statement_ptr(assign_or_copy_construct_statement(our_option, their_option))
if_stmt_inner->if_statement.then_part = assign_or_copy_construct_statement(our_option, their_option)
block->code_block.children.add(if_stmt_inner)
}
} else if (func->function.name == "operator=") {
var other = func->function.parameters[0]
block->code_block.children.add(ast_statement_ptr(make_method_call(replacement_this, "destruct", vector<*ast_node>())))
block->code_block.children.add(ast_statement_ptr(make_method_call(replacement_this, "copy_construct", vector(make_operator_call("&", vector(other))))))
block->code_block.children.add(make_method_call(replacement_this, "destruct", vector<*ast_node>()))
block->code_block.children.add(make_method_call(replacement_this, "copy_construct", vector(make_operator_call("&", vector(other)))))
} else if (func->function.name == "destruct") {
for (var i = 0; i < type_def_option_map[node].size; i++;) {
var option = type_def_option_map[node][i]
@@ -114,7 +114,7 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
if (option_type->indirection == 0 && option_type->is_object() && has_method(option_type->type_def, "destruct", vector<*type>())) {
var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer())))))
var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option))
if_stmt_inner->if_statement.then_part = ast_statement_ptr(make_method_call(our_option, "destruct", vector<*ast_node>()))
if_stmt_inner->if_statement.then_part = make_method_call(our_option, "destruct", vector<*ast_node>())
block->code_block.children.add(if_stmt_inner)
}
}
@@ -138,8 +138,8 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
var block = ast_code_block_ptr()
var value = backing.value
var holder = ast_identifier_ptr(string("holder"), get_ast_type(value)->clone_with_increased_indirection(), block)
block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, null<ast_node>(), false)))
block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(holder, make_operator_call("&", vector(value)))))
block->code_block.children.add(ast_declaration_statement_ptr(holder, null<ast_node>(), false))
block->code_block.children.add(ast_assignment_statement_ptr(holder, make_operator_call("&", vector(value))))
backing.cases.for_each(fun(case_stmt: *ast_node) {
var option = case_stmt->case_statement.option
var flag = get_from_scope(get_ast_type(value)->type_def, "flag")
@@ -158,7 +158,7 @@ fun adt_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
var get_option = make_operator_call(".", vector(make_operator_call("->", vector(holder, data)), option))
get_option = make_operator_call("&", vector(get_option))
unpack_ident->identifier.type = unpack_ident->identifier.type->clone_with_ref()
inner_block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(unpack_ident, get_option, false)))
inner_block->code_block.children.add(ast_declaration_statement_ptr(unpack_ident, get_option, false))
}
inner_block->code_block.children.add(case_stmt->case_statement.statement)
if_stmt->if_statement.then_part = inner_block

View File

@@ -21,7 +21,6 @@ adt ast_node {
function: function,
template: template,
code_block: code_block,
statement: statement,
if_statement: if_statement,
match_statement: match_statement,
case_statement: case_statement,
@@ -458,42 +457,6 @@ obj code_block (Object) {
return children == other.children && scope == other.scope
}
}
fun ast_statement_ptr(child: *ast_node): *ast_node {
var to_ret.construct(child): statement
var ptr = new<ast_node>()
ptr->copy_construct(&ast_node::statement(to_ret))
return ptr
}
fun is_statement(node: *ast_node): bool {
match(*node) {
ast_node::statement(backing) return true
}
return false
}
obj statement (Object) {
var scope: map<string, vector<*ast_node>>
var child: *ast_node
fun construct(child_in: *ast_node): *statement {
child = null<ast_node>()
scope.construct()
child = child_in
return this
}
fun copy_construct(old: *statement) {
scope.copy_construct(&old->scope)
child = old->child
}
fun destruct() {
scope.destruct()
}
fun operator=(other: ref statement) {
destruct()
copy_construct(&other)
}
fun operator==(other: ref statement): bool {
return child == other.child
}
}
fun ast_if_statement_ptr(condition: *ast_node): *ast_node {
var to_ret.construct(condition): if_statement
var ptr = new<ast_node>()
@@ -992,7 +955,7 @@ obj function_call (Object) {
return func == func && parameters == other.parameters
}
}
fun ast_compiler_intrinsic_ptr(intrinsic: string, parameters: vector<string>, type_parameters: vector<*type>, return_type: *type): *ast_node {
fun ast_compiler_intrinsic_ptr(intrinsic: string, parameters: vector<*ast_node>, type_parameters: vector<*type>, return_type: *type): *ast_node {
var to_ret.construct(intrinsic, parameters, type_parameters, return_type): compiler_intrinsic
var ptr = new<ast_node>()
ptr->copy_construct(&ast_node::compiler_intrinsic(to_ret))
@@ -1006,10 +969,10 @@ fun is_compiler_intrinsic(node: *ast_node): bool {
}
obj compiler_intrinsic (Object) {
var intrinsic: string
var parameters: vector<string>
var parameters: vector<*ast_node>
var type_parameters: vector<*type>
var return_type: *type
fun construct(intrinsic_in: string, parameters_in: vector<string>, type_parameters_in: vector<*type>, return_type_in: *type): *compiler_intrinsic {
fun construct(intrinsic_in: string, parameters_in: vector<*ast_node>, type_parameters_in: vector<*type>, return_type_in: *type): *compiler_intrinsic {
intrinsic.copy_construct(&intrinsic_in)
parameters.copy_construct(&parameters_in)
type_parameters.copy_construct(&type_parameters_in)
@@ -1120,7 +1083,6 @@ fun get_ast_children(node: *ast_node): vector<*ast_node> {
ast_node::function(backing) return backing.parameters + backing.body_statement
ast_node::template(backing) return backing.instantiated
ast_node::code_block(backing) return backing.children
ast_node::statement(backing) return vector<*ast_node>(backing.child)
ast_node::if_statement(backing) return vector(backing.condition, backing.then_part, backing.else_part)
ast_node::match_statement(backing) return vector(backing.value) + backing.cases
ast_node::case_statement(backing) return vector(backing.option, backing.unpack_ident, backing.statement)
@@ -1159,7 +1121,6 @@ fun get_ast_name(node: *ast_node): string {
}
ast_node::template(backing) return string("template: ") + backing.name
ast_node::code_block(backing) return string("code_block")
ast_node::statement(backing) return string("statement")
ast_node::if_statement(backing) return string("if_statement")
ast_node::match_statement(backing) return string("match_statement")
ast_node::case_statement(backing) return string("case_statement")
@@ -1189,7 +1150,6 @@ fun get_ast_scope(node: *ast_node): *map<string,vector<*ast_node>> {
ast_node::function() return &node->function.scope
ast_node::template() return &node->template.scope
ast_node::code_block() return &node->code_block.scope
ast_node::statement() return &node->statement.scope
ast_node::if_statement() return &node->if_statement.scope
ast_node::match_statement() return &node->match_statement.scope
ast_node::case_statement() return &node->case_statement.scope

View File

@@ -607,9 +607,7 @@ obj ast_transformation (Object) {
return new_passthrough
}
fun transform_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
var to_ret = ast_statement_ptr(transform(node->children[0], scope, template_replacements));
ast_to_syntax.set(to_ret, node)
return to_ret
return transform(node->children[0], scope, template_replacements);
}
fun transform_declaration_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
// this might have an init position method call
@@ -759,6 +757,7 @@ obj ast_transformation (Object) {
error(node, string("the number of adts found was not 1, it was ") + the_adts.size + " for " + concat_symbol_tree(get_node("scoped_identifier", node)))
var the_adt = the_adts[0]
var the_option_name = concat_symbol_tree(get_node("identifier", get_node("scoped_identifier", node)))
// ADD IN ERROR CHECKING HERE
var the_option = the_adt->adt_def.options.find_first_satisfying(fun(option: *ast_node): bool return option->identifier.name == the_option_name;)
to_ret->case_statement.option = the_option
var possible_ident = get_node("identifier", node)
@@ -779,32 +778,26 @@ obj ast_transformation (Object) {
var func = transform(get_node("unarad", node), scope, search_type::function(parameter_types), template_replacements)
// may return an identifier of type object if doing operator() - but the () have been stripped out by importer
if (get_ast_type(func)->is_object()) {
/*println("Making an operator() method call!")*/
return make_method_call(func, "operator", parameters)
}
var f = ast_function_call_ptr(func, parameters)
/*print("function call function ")*/
/*println(f->function_call.func)*/
/*print("function call parameters ")*/
/*f->function_call.parameters.for_each(fun(param: *ast_node) print(param);)*/
return f
}
fun transform_compiler_intrinsic(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
// don't bother with a full transform for parameters with their own function, just get the boolean expression and transform it
var parameters = vector<string>()
var type_parameters = vector<*type>()
if (get_nodes("intrinsic_parameter", node).size)
parameters = get_nodes("intrinsic_parameter", node).map(fun(child: *tree<symbol>): string return concat_symbol_tree(child);)
if (get_nodes("type", node).size)
type_parameters = get_nodes("type", node).map(fun(child: *tree<symbol>): *type return transform_type(child, scope, template_replacements);)
return ast_compiler_intrinsic_ptr(concat_symbol_tree(get_node("identifier", node)), parameters, type_parameters, type_ptr(base_type::ulong_int()))
/*return ast_compiler_intrinsic_ptr(concat_symbol_tree(get_node("identifier", node)), parameters, type_parameters, type_ptr(base_type::integer()))*/
var parameters = get_nodes("parameter", node).map(fun(child: *tree<symbol>): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);)
var type_parameters = get_nodes("type", node).map(fun(child: *tree<symbol>): *type return transform_type(child, scope, template_replacements);)
var intrinsic_name = concat_symbol_tree(get_node("identifier", node))
var intrinsic_return_type: *type
if (intrinsic_name == "ctce")
intrinsic_return_type = get_ast_type(parameters[0])
else
intrinsic_return_type = type_ptr(base_type::ulong_int())
return ast_compiler_intrinsic_ptr(intrinsic_name, parameters, type_parameters, intrinsic_return_type)
}
fun transform_lambda(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
var function_node = second_pass_function(node, scope, template_replacements, false)
function_node->function.body_statement = transform_statement(get_node("statement", node), function_node, template_replacements)
function_node->function.closed_variables = find_closed_variables(function_node, function_node->function.body_statement)
/*println(string("Found ") + function_node->function.closed_variables.size() + " closed variables!")*/
while (!is_translation_unit(scope)) scope = get_ast_scope(scope)->get(string("~enclosing_scope"))[0]
scope->translation_unit.lambdas.add(function_node)
return function_node
@@ -816,9 +809,6 @@ obj ast_transformation (Object) {
if (!in_scope_chain(backing.enclosing_scope, func))
return set(node);
}
ast_node::statement(backing) {
return find_closed_variables(func, backing.child)
}
ast_node::code_block(backing) {
var to_ret = set<*ast_node>()
backing.children.for_each(fun(n: *ast_node) to_ret += find_closed_variables(func, n);)
@@ -894,7 +884,8 @@ obj ast_transformation (Object) {
return in_scope_chain(get_ast_scope(node)->get(string("~enclosing_scope"))[0], high_scope)
return false
}
fun transform_expression(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node return transform_expression(node, scope, search_type::none(), template_replacements)
fun transform_expression(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node
return transform_expression(node, scope, search_type::none(), template_replacements)
fun transform_expression(node: *tree<symbol>, scope: *ast_node, searching_for: search_type, template_replacements: map<string, *type>): *ast_node {
var func_name = string()
var parameters = vector<*ast_node>()

View File

@@ -229,8 +229,8 @@ obj c_generator (Object) {
if (!backing.is_extern)
function_definitions += prototype_and_header.second
if (backing.body_statement) {
function_definitions += string(" {\n") + generate_statement(backing.body_statement, enclosing_object, child).one_string()
function_definitions += "}\n"
function_definitions += string(" {\n") + generate(backing.body_statement, enclosing_object, child, false).one_string()
function_definitions += ";\n}\n"
} else if (!backing.is_extern) {
error("Empty function statement and not extern - no ADTs anymore!")
}
@@ -256,8 +256,8 @@ obj c_generator (Object) {
match (*child) {
// should really check the genrator
ast_node::if_comp(backing) {
if (is_simple_passthrough(backing.statement->statement.child))
top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child, true)
if (is_simple_passthrough(backing.statement))
top_level_c_passthrough += generate_simple_passthrough(backing.statement, true)
}
ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child, true)
ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null<ast_node>(), null<ast_node>(), false).one_string() + ";\n" // false - don't do defer
@@ -368,7 +368,6 @@ obj c_generator (Object) {
return pre + result + post
return pre + "{" + result + "}" + post
}
fun generate_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple return generate(node->statement.child, enclosing_object, enclosing_func, false) + ";\n";
fun generate_declaration_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, add_to_defer: bool): code_triple {
var identifier = node->declaration_statement.identifier
var ident_type = identifier->identifier.type
@@ -508,7 +507,7 @@ obj c_generator (Object) {
}
fun generate_code_block(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple {
var to_ret = code_triple("{\n")
node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, false).one_string();)
node->code_block.children.for_each(fun(child: *ast_node) to_ret += generate(child, enclosing_object, enclosing_func, false).one_string() + ";\n";)
return to_ret + "}"
}
// this generates the function as a value, not the actual function
@@ -682,8 +681,8 @@ obj c_generator (Object) {
error("wrong parameters to sizeof compiler intrinsic")
return code_triple("sizeof(") + type_to_c(node->compiler_intrinsic.type_parameters[0]) + ")"
} else if (node->compiler_intrinsic.intrinsic == "link") {
node->compiler_intrinsic.parameters.for_each(fun(str: string) {
linker_string += string("-l") + str + " "
node->compiler_intrinsic.parameters.for_each(fun(value: *ast_node) {
linker_string += string("-l") + value->value.string_value.slice(1,-2) + " "
})
return code_triple()
}
@@ -697,7 +696,6 @@ obj c_generator (Object) {
match (*node) {
ast_node::if_comp(backing) return generate_if_comp(node, enclosing_object, enclosing_func)
ast_node::simple_passthrough(backing) return code_triple() + generate_simple_passthrough(node, false)
ast_node::statement(backing) return generate_statement(node, enclosing_object, enclosing_func)
ast_node::declaration_statement(backing) return generate_declaration_statement(node, enclosing_object, enclosing_func, true)
ast_node::assignment_statement(backing) return generate_assignment_statement(node, enclosing_object, enclosing_func)
ast_node::if_statement(backing) return generate_if_statement(node, enclosing_object, enclosing_func)

View File

@@ -20,18 +20,16 @@ fun get_line(node: *tree<symbol>, name: string): *ast_node {
fun c_line_control(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
var first = true
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
var helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*node) {
ast_node::statement(backing) {
if (is_code_block(parent_chain->top()) && ast_to_syntax->contains_key(node)) {
/*var helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {*/
/*match(*node) {*/
/*if (is_code_block(parent_chain->top()) && ast_to_syntax->contains_key(node)) {*/
/*println(string("adding ") + get_ast_name(node) + " to " + get_ast_name(parent))*/
add_before_in(get_line(ast_to_syntax->get(node), name), node, parent_chain->top())
}
}
}
}
if (first)
run_on_tree(helper, empty_pass_second_half, syntax_ast_pair.second)
/*add_before_in(get_line(ast_to_syntax->get(node), name), node, parent_chain->top())*/
/*}*/
/*}*/
/*}*/
/*if (first)*/
/*run_on_tree(helper, empty_pass_second_half, syntax_ast_pair.second)*/
first = false
})
}

30
stdlib/ctce_lower.krak Normal file
View File

@@ -0,0 +1,30 @@
import symbol:*
import tree:*
import vector:*
import map:*
import util:*
import string:*
import mem:*
import io:*
import ast_nodes:*
import ast_transformation:*
import interpreter:*
import pass_common:*
fun ctce_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree<symbol>>) {
name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree<symbol>,*ast_node>) {
var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*node) {
ast_node::compiler_intrinsic(backing) {
if (backing.intrinsic == "ctce") {
var result = evaluate_constant_expression(backing.parameters[0])
*node = *unwrap_value(result)
}
}
}
}
run_on_tree(helper_before, empty_pass_second_half, syntax_ast_pair.second)
})
}

View File

@@ -19,8 +19,8 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*node) {
ast_node::defer_statement(backing) {
if (is_code_block(parent_chain->top()) || (is_statement(parent_chain->top()) && is_code_block(parent_chain->from_top(1)))) {
remove_full_statement(node, parent_chain)
if (is_code_block(parent_chain->top())) {
remove(node, parent_chain)
defer_double_stack.top().push(backing.statement)
} else {
replace_with_in(node, backing.statement, parent_chain)
@@ -47,7 +47,7 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
replace_with_in(node, block, parent_chain)
for (var i = 0; i < defer_double_stack.size() - loop_stack.top(); i++;)
block->code_block.children.add_all(defer_double_stack.from_top(i).reverse_vector())
block->code_block.children.add(ast_statement_ptr(node))
block->code_block.children.add(node)
}
ast_node::return_statement(backing) {
var block = ast_code_block_ptr()
@@ -57,8 +57,8 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
if (get_ast_type(enclosing_function)->return_type->is_ref)
return_value = make_operator_call("&", vector(return_value))
var temp_return = ast_identifier_ptr("temp_boom_return", get_ast_type(return_value)->clone_without_ref(), block)
block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(temp_return, null<ast_node>(), false)))
block->code_block.children.add(ast_statement_ptr(assign_or_copy_construct_statement(temp_return, return_value)))
block->code_block.children.add(ast_declaration_statement_ptr(temp_return, null<ast_node>(), false))
block->code_block.children.add(assign_or_copy_construct_statement(temp_return, return_value))
// dereference so that the real ref can take it back
if (get_ast_type(enclosing_function)->return_type->is_ref)
temp_return = make_operator_call("*", vector(temp_return))
@@ -66,7 +66,7 @@ fun defer_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_t
}
for (var i = 0; i < defer_double_stack.size(); i++;)
block->code_block.children.add_all(defer_double_stack.from_top(i).reverse_vector())
block->code_block.children.add(ast_statement_ptr(node))
block->code_block.children.add(node)
}
ast_node::code_block(backing) {
node->code_block.children.add_all(defer_double_stack.pop().reverse_vector())

View File

@@ -119,6 +119,33 @@ fun wrap_value(val: *ast_node): value {
error("Could not wrap value")
return value::void_nothing()
}
fun unwrap_value(val: value): *ast_node {
// string, char, bool, floating
var value_string = string()
match (get_real_value(val)) {
value::boolean(data) value_string = to_string(data)
value::character(data) value_string = to_string(data)
value::ucharacter(data) value_string = to_string(data)
value::short_int(data) value_string = to_string(data)
value::ushort_int(data) value_string = to_string(data)
value::integer(data) value_string = to_string(data)
value::uinteger(data) value_string = to_string(data)
value::long_int(data) value_string = to_string(data)
value::ulong_int(data) value_string = to_string(data)
value::floating(data) value_string = to_string(data)
value::double_precision(data) value_string = to_string(data)
value::void_nothing() error("trying to unwrap a void into an ast_value_ptr")
value::pointer(point) {
if (point.second->base == base_type::character() && point.second->indirection == 1)
value_string = string("\"") + string((point.first) cast *char) + "\""
else
error("trying to unwrap a pointer into an ast_value_ptr")
}
value::object_like(ob) error("trying to unwrap an object_like into an ast_value_ptr")
value::function(fn) error("trying to unwrap a function into an ast_value_ptr")
}
return ast_value_ptr(value_string, get_type_from_primitive_value(get_real_value(val)))
}
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; }
@@ -799,9 +826,6 @@ fun interpret_function(function: *ast_node, var_stack: *stack<map<*ast_node, val
})
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, globals: *map<*ast_node, value>): pair<value, control_flow> {
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, globals: *map<*ast_node, value>): pair<value, control_flow> {
var_stack->push(map<*ast_node,value>())
var value_from_inside = make_pair(value::void_nothing(), control_flow::nor())
@@ -974,7 +998,6 @@ fun interpret(node: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosi
match (*node) {
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, globals)
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, globals)
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, globals)

View File

@@ -4,7 +4,6 @@ import mem:*
ext fun printf(fmt_str: *char, ...): int
ext fun fprintf(file: *void, format: *char, ...): int
ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int
ext fun fflush(file: int): int
ext var stderr: *void
ext fun fgets(buff: *char, size: int, file: *void): *char
@@ -63,16 +62,6 @@ fun print(toPrint: bool) {
else
print("false")
}
fun print(toPrint: float)
print((toPrint) cast double)
fun print(toPrint: double) {
var how_much = snprintf(null<char>(), (0) cast ulong, "%f", toPrint)
var int_str = new<char>(how_much+2)
snprintf(int_str, (how_much+1) cast ulong, "%f", toPrint)
print(int_str)
delete(int_str)
}
fun print<T>(toPrint: T): void
print(string::to_string(toPrint))

View File

@@ -1,3 +1,4 @@
/*#link("m")*/
#link(m)
fun fibanacci(num: int): int {

View File

@@ -25,10 +25,10 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
// Pass 1
var ensure_block_and_munge = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {
match(*node) {
ast_node::function(backing) if (backing.body_statement && !is_code_block(backing.body_statement)) backing.body_statement = ast_statement_ptr(ast_code_block_ptr(backing.body_statement))
ast_node::function(backing) if (backing.body_statement && !is_code_block(backing.body_statement)) backing.body_statement = ast_code_block_ptr(backing.body_statement)
ast_node::if_statement(backing) {
if (!is_code_block(backing.then_part)) backing.then_part = ast_statement_ptr(ast_code_block_ptr(backing.then_part))
if (backing.else_part && !is_code_block(backing.else_part)) backing.else_part = ast_statement_ptr(ast_code_block_ptr(backing.else_part))
if (!is_code_block(backing.then_part)) backing.then_part = ast_code_block_ptr(backing.then_part)
if (backing.else_part && !is_code_block(backing.else_part)) backing.else_part = ast_code_block_ptr(backing.else_part)
}
// no need for case because it's already been lowered
ast_node::while_loop(backing) {
@@ -37,33 +37,33 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
backing.condition = ast_value_ptr(string("true"), type_ptr(base_type::boolean()))
// objects do not coerce to booleans, so it should be ok for this not to be a ref
var condition_ident = ast_identifier_ptr("condition_temp", get_ast_type(condition), backing.statement)
backing.statement->code_block.children.add(0, ast_statement_ptr(ast_declaration_statement_ptr(condition_ident, condition, false)))
backing.statement->code_block.children.add(0, ast_declaration_statement_ptr(condition_ident, condition, false))
var condition_if = ast_if_statement_ptr(make_operator_call("!", vector(condition_ident)))
condition_if->if_statement.then_part = ast_statement_ptr(ast_branching_statement_ptr(branching_type::break_stmt()))
backing.statement->code_block.children.add(1, ast_statement_ptr(condition_if))
condition_if->if_statement.then_part = ast_branching_statement_ptr(branching_type::break_stmt())
backing.statement->code_block.children.add(1, condition_if)
}
ast_node::for_loop(backing) {
if (!is_code_block(backing.body)) backing.body = ast_code_block_ptr(backing.body)
add_before_in(backing.init, parent_chain->top(), parent_chain->from_top(1))
add_before_in(backing.init, node, parent_chain->top())
backing.init = null<ast_node>()
// the do_update goes in the block above the for
var update_ident = ast_identifier_ptr("do_update", type_ptr(base_type::boolean()), parent_chain->from_top(1))
add_before_in(ast_statement_ptr(ast_declaration_statement_ptr(update_ident, ast_value_ptr(string("false"), type_ptr(base_type::boolean())), false)),
parent_chain->top(), parent_chain->from_top(1))
var update_ident = ast_identifier_ptr("do_update", type_ptr(base_type::boolean()), parent_chain->top())
add_before_in(ast_declaration_statement_ptr(update_ident, ast_value_ptr(string("false"), type_ptr(base_type::boolean())), false),
node, parent_chain->top())
var update_if = ast_if_statement_ptr(update_ident)
update_if->if_statement.then_part = ast_statement_ptr(ast_code_block_ptr(backing.update))
update_if->if_statement.then_part = ast_code_block_ptr(backing.update)
backing.update = null<ast_node>()
backing.body->code_block.children.add(0, ast_statement_ptr(update_if))
backing.body->code_block.children.add(1, ast_statement_ptr(ast_assignment_statement_ptr(update_ident, ast_value_ptr(string("true"), type_ptr(base_type::boolean())))))
backing.body->code_block.children.add(0, update_if)
backing.body->code_block.children.add(1, ast_assignment_statement_ptr(update_ident, ast_value_ptr(string("true"), type_ptr(base_type::boolean()))))
var condition = backing.condition
backing.condition = ast_value_ptr(string("true"), type_ptr(base_type::boolean()))
// objects do not coerce to booleans, so it should be ok for this not to be a ref
var condition_ident = ast_identifier_ptr("condition_temp", get_ast_type(condition), backing.body)
backing.body->code_block.children.add(2, ast_statement_ptr(ast_declaration_statement_ptr(condition_ident, condition, false)))
backing.body->code_block.children.add(2, ast_declaration_statement_ptr(condition_ident, condition, false))
var condition_if = ast_if_statement_ptr(make_operator_call("!", vector(condition_ident)))
condition_if->if_statement.then_part = ast_statement_ptr(ast_branching_statement_ptr(branching_type::break_stmt()))
backing.body->code_block.children.add(3, ast_statement_ptr(condition_if))
condition_if->if_statement.then_part = ast_branching_statement_ptr(branching_type::break_stmt())
backing.body->code_block.children.add(3, condition_if)
}
}
}
@@ -87,15 +87,15 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
if (func_name == "||" || func_name == "&&") {
var enclosing_block_idx = parent_chain->index_from_top_satisfying(fun(i: *ast_node): bool return is_code_block(i);)
var short_circuit_result = ast_identifier_ptr("short_circut_result", type_ptr(base_type::boolean()), parent_chain->from_top(enclosing_block_idx))
var short_circuit_declaration = ast_statement_ptr(ast_declaration_statement_ptr(short_circuit_result, backing.parameters[0], false))
var short_circuit_declaration = ast_declaration_statement_ptr(short_circuit_result, backing.parameters[0], false)
var condition = short_circuit_result
if (func_name == "||")
condition = make_operator_call("!", vector(condition))
var short_circuit_if = ast_if_statement_ptr(condition)
// how to get proper parent scoping working for this part
short_circuit_if->if_statement.then_part = ast_code_block_ptr(ast_statement_ptr(ast_assignment_statement_ptr(short_circuit_result, backing.parameters[1])))
short_circuit_if->if_statement.then_part = ast_code_block_ptr(ast_assignment_statement_ptr(short_circuit_result, backing.parameters[1]))
add_before_in(short_circuit_declaration, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
add_before_in(ast_statement_ptr(short_circuit_if), parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
add_before_in(short_circuit_if, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
replace_with_in(node, short_circuit_result, parent_chain)
var shorter_tree = stack_from_vector( parent_chain->data.slice(0, parent_chain->size()-enclosing_block_idx))
run_on_tree_helper(short_circut_op, empty_pass_second_half, short_circuit_declaration, &shorter_tree, false)
@@ -124,6 +124,12 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
return
}
var enclosing_block_idx = parent_chain->index_from_top_satisfying(fun(i: *ast_node): bool return is_code_block(i);)
var replace_before: *ast_node
if (enclosing_block_idx > 0)
replace_before = parent_chain->from_top(enclosing_block_idx-1)
else
replace_before = node
var replace_in = parent_chain->from_top(enclosing_block_idx)
var func_type = get_ast_type(backing.func)
for (var i = 0; i < backing.parameters.size; i++;) {
var param = backing.parameters[i]
@@ -136,20 +142,20 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
var param_type = get_ast_type(param)
if (!in_function_param_type->is_ref && param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1))))) {
var temp_ident = ast_identifier_ptr("temporary_param_boom", param_type->clone_without_ref(), null<ast_node>())
var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_ident, null<ast_node>(), false))
var copy_in = ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param)))))
add_before_in(declaration, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
add_before_in(copy_in, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>(), false)
var copy_in = make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))
add_before_in(declaration, replace_before, replace_in)
add_before_in(copy_in, replace_before, replace_in)
backing.parameters[i] = temp_ident
}
}
var func_return_type = func_type->return_type
if (!func_return_type->is_ref && func_return_type->indirection == 0 && (func_return_type->is_object() && has_method(func_return_type->type_def, "destruct", vector<*type>()))) {
var temp_return = ast_identifier_ptr("temporary_return_boomchaka", func_return_type, null<ast_node>())
var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_return, node, false))
add_before_in(declaration, parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
add_before_in(ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(temp_return, "destruct", vector<*ast_node>())))),
parent_chain->from_top(enclosing_block_idx-1), parent_chain->from_top(enclosing_block_idx))
var declaration = ast_declaration_statement_ptr(temp_return, node, false)
add_before_in(declaration, replace_before, replace_in)
add_before_in(ast_defer_statement_ptr(make_method_call(temp_return, "destruct", vector<*ast_node>())),
replace_before, replace_in)
replace_with_in(node, temp_return, parent_chain)
}
}
@@ -159,8 +165,8 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
var param_type = get_ast_type(param)
if (!param_type->is_ref && param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "destruct", vector<*type>()))) {
// the first pass ensures a code_block child
backing.body_statement->statement.child->code_block.children.add(order++,
ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(param, "destruct", vector<*ast_node>())))))
backing.body_statement->code_block.children.add(order++,
ast_defer_statement_ptr(make_method_call(param, "destruct", vector<*ast_node>())))
}
})
}
@@ -171,18 +177,18 @@ fun obj_lower(name_ast_map: *map<string, pair<*tree<symbol>,*ast_node>>, ast_to_
if (!ident_type->is_ref && ident_type->indirection == 0 && ident_type->is_object()) {
if (backing.expression && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(backing.expression)->clone_with_increased_indirection()))) {
var temp_cpy_ctst = ast_identifier_ptr("temp_declaration_copy_construct", get_ast_type(backing.expression)->clone_without_ref(), null<ast_node>())
var declaration = ast_statement_ptr(ast_declaration_statement_ptr(temp_cpy_ctst, backing.expression, false))
add_after_in(ast_statement_ptr(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(temp_cpy_ctst))))),
parent_chain->top(), parent_chain->from_top(1))
var declaration = ast_declaration_statement_ptr(temp_cpy_ctst, backing.expression, false)
add_after_in(make_method_call(backing.identifier, "copy_construct", vector(make_operator_call("&", vector(temp_cpy_ctst)))),
node, parent_chain->top())
// do second so the order's right
add_after_in(declaration,
parent_chain->top(), parent_chain->from_top(1))
node, parent_chain->top())
backing.expression = null<ast_node>()
}
if (has_method(ident_type->type_def, "destruct", vector<*type>())) {
// have to go up one because our parent is a statement
add_after_in(ast_statement_ptr(ast_defer_statement_ptr(ast_statement_ptr(make_method_call(backing.identifier, "destruct", vector<*ast_node>())))),
parent_chain->top(), parent_chain->from_top(1))
add_after_in(ast_defer_statement_ptr(make_method_call(backing.identifier, "destruct", vector<*ast_node>())),
node, parent_chain->top())
}
}
}

View File

@@ -262,15 +262,6 @@ fun get_children_pointer(node: *ast_node): *vector<*ast_node> {
}
return bc
}
fun remove_full_statement(node: *ast_node, parent_chain: *stack<*ast_node>): *ast_node {
if (is_statement(node))
return remove(node, parent_chain)
if (is_statement(parent_chain->top()))
return remove(parent_chain->top(), parent_chain->from_top(1))
error(string("cannot remove full statement in ") + get_ast_name(parent_chain->top()))
}
fun remove(orig: *ast_node, in: *stack<*ast_node>): *ast_node
return remove(orig, in->top())
fun remove(orig: *ast_node, in: *ast_node): *ast_node {
@@ -289,7 +280,6 @@ fun replace_with_in(orig: *ast_node, new: *ast_node, in: *stack<*ast_node>)
replace_with_in(orig, new, in->top())
fun replace_with_in(orig: *ast_node, new: *ast_node, in: *ast_node) {
match (*in) {
ast_node::statement(backing) { backing.child = new; return; }
ast_node::return_statement(backing) { backing.return_value = new; return; }
ast_node::assignment_statement(backing) {
if (backing.to == orig) {
@@ -431,7 +421,6 @@ fun run_on_tree_helper(func_before: fun(*ast_node,*stack<*ast_node>):bool, func_
ast_node::function(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
ast_node::template(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, true);)
ast_node::code_block(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
ast_node::statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
ast_node::if_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
ast_node::match_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)
ast_node::case_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain, false);)

View File

@@ -4,9 +4,22 @@ import mem
import serialize
import io
/*fun to_string(in: bool): string*/
/*if (in) return string("true")*/
/*else return string("false")*/
ext fun snprintf(to_str: *char, num: ulong, format: *char, ...): int
fun to_string(in: float): string
return to_string((in) cast double)
fun to_string(in: double): string {
var how_much = snprintf(mem::null<char>(), (0) cast ulong, "%f", in)
var int_str = mem::new<char>(how_much+2)
snprintf(int_str, (how_much+1) cast ulong, "%f", in)
var to_ret = string(int_str)
mem::delete(int_str)
return to_ret
}
fun to_string(in: bool): string
if (in) return string("true")
else return string("false")
fun to_string(in: char): string
return string(in)
fun to_string(in: uchar): string
return to_string_num(in)
fun to_string(in: short): string
@@ -98,10 +111,6 @@ obj string (Object, Serializable) {
data.construct(len);
data.set_size(len);
mem::memmove((data.getBackingMemory()) cast *void, (str) cast *void, (len) cast ulong)
/*while(*str) {*/
/*data.addEnd(*str);*/
/*str += 1;*/
/*}*/
// no null terminator
return this;
}

View File

@@ -3,6 +3,7 @@ import os:*
import mem:*
import util:*
/*#link("pthread")*/
#link(pthread)
ext fun pthread_attr_init(attr_ptr: *void): int
ext fun pthread_create(thread: *ulong, attr_ptr: *void, func: *void, param: *void): int

View File

@@ -226,6 +226,10 @@ obj vector<T> (Object, Serializable) {
}
fun add(index: int, dataIn: ref T) {
if (size == 0) {
add(dataIn)
return
}
add(last())
for (var i = size-2; i > index; i--;) {
data[i] = data[i-1]