From: Ben Sherratt Date: Sat, 13 Feb 2021 10:41:36 +0000 (+0000) Subject: Initial commit X-Git-Url: https://git.bts.cx/sun.git/commitdiff_plain/c14e8cb22c12114bd78aae89e54ccd51ad522c50?ds=sidebyside Initial commit --- c14e8cb22c12114bd78aae89e54ccd51ad522c50 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6890ab6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.10) + +project(sun C) + +add_subdirectory(core) +add_subdirectory(compiler) +add_subdirectory(vm) + +#add_subdirectory(tests) diff --git a/aot/c_generator.c b/aot/c_generator.c new file mode 100644 index 0000000..4458fbe --- /dev/null +++ b/aot/c_generator.c @@ -0,0 +1,321 @@ +#include "c_generator.h" + +#include "node_internal.h" +#include "node_type.h" + +#include + +static int c_generator_output_node(FILE *output_file, Node *node); +static int c_generator_output_sequence_node(FILE *output_file, Node *node, const char *separator); +static bool c_generator_is_prefix_unary_operator(OperatorType operator_type); +static char *c_generator_operator_string(OperatorType operator_type); + +int c_generator_generate_module(FILE *output_file, Node *module) { + return c_generator_output_node(output_file, module); +} + +static int c_generator_output_node(FILE *output_file, Node *node) { + if (node != NULL) { + switch (node->type) { + case NodeTypeUnknown: + return -1; + + case NodeTypeIdentifier: + fprintf(output_file, "%s", node->string_value); + break; + + case NodeTypeInteger: + fprintf(output_file, "%d", node->integer_value); + break; + + case NodeTypeFloat: + fprintf(output_file, "%f", node->float_value); + break; + + case NodeTypeString: + fprintf(output_file, "%s", node->string_value); // NB: Quotes are left in by lexer + break; + + case NodeTypeCompound: + fprintf(output_file, "("); + c_generator_output_node(output_file, node->compound_subexpression); + fprintf(output_file, ")"); + break; + + case NodeTypeArgument: + c_generator_output_node(output_file, node->argument_expression); + break; + + case NodeTypeArrayAccess: + c_generator_output_node(output_file, node->array_access_array); + fprintf(output_file, "["); + c_generator_output_node(output_file, node->array_access_access); + fprintf(output_file, "]"); + break; + + case NodeTypeTypeAccess: + c_generator_output_node(output_file, node->type_access_type); + fprintf(output_file, "."); + c_generator_output_node(output_file, node->type_access_access); + break; + + case NodeTypeFunctionCall: + c_generator_output_node(output_file, node->function_call_function); + fprintf(output_file, "("); + c_generator_output_sequence_node(output_file, node->function_call_parameters, ","); + fprintf(output_file, ")"); + break; + + + case NodeTypeUnaryOperation: + if (c_generator_is_prefix_unary_operator(node->unary_operation_operator->operator_type)) { + c_generator_output_node(output_file, node->unary_operation_operator); + c_generator_output_node(output_file, node->unary_operation_operand); + } else { + c_generator_output_node(output_file, node->unary_operation_operand); + c_generator_output_node(output_file, node->unary_operation_operator); + } + break; + + case NodeTypeBinaryOperation: + c_generator_output_node(output_file, node->binary_operation_lhs); + c_generator_output_node(output_file, node->binary_operation_operator); + c_generator_output_node(output_file, node->binary_operation_rhs); + break; + + case NodeTypeOperator: + fprintf(output_file, "%s", c_generator_operator_string(node->operator_type)); + break; + + case NodeTypeAssignment: + c_generator_output_node(output_file, node->assignment_target); + fprintf(output_file, "="); + c_generator_output_node(output_file, node->assignment_source); + break; + + case NodeTypeForIteration: + fprintf(output_file, "for ("); + c_generator_output_node(output_file, node->iteration_initial_expression); + fprintf(output_file, ";"); + c_generator_output_node(output_file, node->iteration_pre_valid_expression); + fprintf(output_file, ";"); + c_generator_output_node(output_file, node->iteration_loop_expression); + fprintf(output_file, ") "); + c_generator_output_node(output_file, node->iteration_statement); + break; + + case NodeTypeDoIteration: + fprintf(output_file, "do "); + c_generator_output_node(output_file, node->iteration_statement); + fprintf(output_file, " while ("); + c_generator_output_node(output_file, node->iteration_post_valid_expression); + fprintf(output_file, ")"); + break; + + case NodeTypeWhileIteration: + fprintf(output_file, "while ("); + c_generator_output_node(output_file, node->iteration_pre_valid_expression); + fprintf(output_file, ") "); + c_generator_output_node(output_file, node->iteration_statement); + break; + + case NodeTypeSelection: + fprintf(output_file, "if ("); + c_generator_output_node(output_file, node->selection_valid_expression); + fprintf(output_file, ") "); + c_generator_output_node(output_file, node->selection_valid_statement); + if (node->selection_invalid_statement != NULL) { + fprintf(output_file, " else "); + c_generator_output_node(output_file, node->selection_invalid_statement); + } + break; + + case NodeTypeStatement: + c_generator_output_node(output_file, node->statement_contents); + fprintf(output_file, ";\n"); + break; + + case NodeTypeVariableDefinition: + c_generator_output_node(output_file, node->variable_definition_type); + fprintf(output_file, " "); + c_generator_output_node(output_file, node->variable_definition_identifier); + if (node->variable_definition_default_expression) { + fprintf(output_file, "="); + c_generator_output_node(output_file, node->variable_definition_default_expression); + } + break; + + case NodeTypeTypeDefinition: + fprintf(output_file, "typedef struct "); + c_generator_output_node(output_file, node->type_definition_identifier); + fprintf(output_file, " {\n"); + c_generator_output_sequence_node(output_file, node->type_definition_members, NULL); + fprintf(output_file, "} "); + c_generator_output_node(output_file, node->type_definition_identifier); + fprintf(output_file, ";\n"); + break; + + case NodeTypeTypeMemberDefinition: + c_generator_output_node(output_file, node->type_member_definition_type); + fprintf(output_file, " "); + c_generator_output_node(output_file, node->type_member_definition_identifier); + fprintf(output_file, ";\n"); + break; + + case NodeTypeFunctionDefinition: + c_generator_output_node(output_file, node->function_definition_type); + fprintf(output_file, " "); + c_generator_output_node(output_file, node->function_definition_identifier); + fprintf(output_file, "("); + c_generator_output_sequence_node(output_file, node->function_definition_parameters, ","); + fprintf(output_file, ")"); + c_generator_output_node(output_file, node->function_definition_body); + break; + + case NodeTypeFunctionParameterDefinition: + c_generator_output_node(output_file, node->function_parameter_definition_type); + fprintf(output_file, " "); + c_generator_output_node(output_file, node->function_parameter_definition_identifier); + break; + + case NodeTypeModule: + c_generator_output_sequence_node(output_file, node->module_definitions, NULL); + break; + + case NodeTypeSequence: + fprintf(output_file, "{\n"); + c_generator_output_sequence_node(output_file, node, NULL); + fprintf(output_file, "}"); + break; + } + } + + return 0; +} + +static int c_generator_output_sequence_node(FILE *output_file, Node *node, const char *separator) { + if (node != NULL) { + if (node->type != NodeTypeSequence) { + c_generator_output_node(output_file, node); + } else { + while (node != NULL) { + c_generator_output_node(output_file, node->sequence_node); + if (separator != NULL && node->sequence_next != NULL) fprintf(output_file, "%s", separator); + node = node->sequence_next; + } + } + } + + return 0; +} + +static bool c_generator_is_prefix_unary_operator(OperatorType operator_type) { + switch (operator_type) { + case OperatorTypeUnknown: + // FIXME, should never reach here + + case OperatorTypeAdd: + case OperatorTypeSubtract: + case OperatorTypeMultiply: + case OperatorTypeDivide: + case OperatorTypeModulo: + case OperatorTypePositive: + case OperatorTypeNegative: + case OperatorTypeBitwiseAnd: + case OperatorTypeBitwiseOr: + case OperatorTypeBitwiseXor: + case OperatorTypeBitwiseNot: + case OperatorTypeLogicalAnd: + case OperatorTypeLogicalOr: + case OperatorTypeLogicalNot: + case OperatorTypeEqual: + case OperatorTypeNotEqual: + case OperatorTypeLessThan: + case OperatorTypeLessThanEqual: + case OperatorTypeGreaterThan: + case OperatorTypeGreaterThanEqual: + case OperatorTypePreIncrement: + case OperatorTypePreDecrement: + return true; + + case OperatorTypePostIncrement: + case OperatorTypePostDecrement: + return false; + } +} + +char *c_generator_operator_string(OperatorType operator_type) { + switch (operator_type) { + default: + case OperatorTypeUnknown: + return ""; // FIXME, should never reach here + + case OperatorTypeAdd: + return "+"; + + case OperatorTypeSubtract: + return "-"; + + case OperatorTypeMultiply: + return "*"; + + case OperatorTypeDivide: + return "/"; + + case OperatorTypeModulo: + return "%"; + + case OperatorTypePositive: + return "+"; + + case OperatorTypeNegative: + return "-"; + + case OperatorTypeBitwiseAnd: + return "&"; + + case OperatorTypeBitwiseOr: + return "|"; + + case OperatorTypeBitwiseXor: + return "^"; + + case OperatorTypeBitwiseNot: + return "~"; + + case OperatorTypeLogicalAnd: + return "&&"; + + case OperatorTypeLogicalOr: + return "||"; + + case OperatorTypeLogicalNot: + return "!"; + + case OperatorTypeEqual: + return "=="; + + case OperatorTypeNotEqual: + return "!="; + + case OperatorTypeLessThan: + return "<"; + + case OperatorTypeLessThanEqual: + return "<="; + + case OperatorTypeGreaterThan: + return ">"; + + case OperatorTypeGreaterThanEqual: + return ">="; + + case OperatorTypePreIncrement: + case OperatorTypePostIncrement: + return "++"; + + case OperatorTypePreDecrement: + case OperatorTypePostDecrement: + return "--"; + } +} diff --git a/aot/c_generator.h b/aot/c_generator.h new file mode 100644 index 0000000..c970c1b --- /dev/null +++ b/aot/c_generator.h @@ -0,0 +1,9 @@ +#ifndef C_GENERATOR_H +#define C_GENERATOR_H + +#include "node.h" +#include + +extern int c_generator_generate_module(FILE *output_file, Node *module); + +#endif diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt new file mode 100644 index 0000000..26c416c --- /dev/null +++ b/runtime/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.10) + +find_package(BISON) +find_package(FLEX) + +project(sun C) + +BISON_TARGET(SunParser ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/sun.y ${CMAKE_CURRENT_BINARY_DIR}/sun_parser.c COMPILE_FLAGS -v) +FLEX_TARGET(SunScanner ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/sun.l ${CMAKE_CURRENT_BINARY_DIR}/sun_lexer.c COMPILE_FLAGS --header-file=${CMAKE_CURRENT_BINARY_DIR}/sun_lexer.h) +ADD_FLEX_BISON_DEPENDENCY(SunScanner SunParser) + +set(SUN_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/compiler.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/compiler_internal.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/compiler.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/vm_generator.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/compiler/vm_generator.c + + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/crc32.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/data_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/data_type.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/node.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/node.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/node_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/node_type.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/operator_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/operator_type.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/tree.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/tree/tree.c + + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/vm/fixed.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/vm/fixed.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/vm/instruction.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/vm/instruction.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/vm/vm.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/sun/vm/vm.c + + ${BISON_SunParser_OUTPUTS} + ${FLEX_SunScanner_OUTPUTS} +) + +add_library(sun ${SUN_SOURCES}) + +#add_executable(suncc ${SUNCC_SOURCES}) +target_include_directories(sun PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # So the Flex/Bison code can find header +target_include_directories(sun PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # So our code can find Flex/Bison code +#target_link_libraries(sun suncore) +#target_link_libraries(suncc ${FLEX_LIBRARIES}) diff --git a/runtime/src/sun/compiler/compiler.c b/runtime/src/sun/compiler/compiler.c new file mode 100644 index 0000000..4ce214f --- /dev/null +++ b/runtime/src/sun/compiler/compiler.c @@ -0,0 +1,44 @@ +#include + +#include + +#include "sun_parser.h" // This needs to be first. +#include "sun_lexer.h" + +#include +#include +#include +#include + +extern int yyparse(SLTNode **moduleOut, yyscan_t *scanner); + +SVMModule *slcCompileSource(const SLCCompileConfiguration *configuration) { + yyscan_t sc; + int res; + SLCLexerExtra extra; + + extra.readCallback = configuration->sourceReadCallback; + extra.readCallbackParameter = configuration->sourceUserParam; + + yylex_init_extra(&extra, &sc); + SLTNode *module = NULL; + int parse_return = yyparse(&module, sc); + yylex_destroy(sc); + + switch (parse_return) { + case 0: + return slcGenerateVMInstructions(module); + + case 1: + printf("Error\n"); + return NULL; + + case 2: + printf("Out of memory\n"); + return NULL; + + default: + printf("Unknown error...\n"); + return NULL; + } +} diff --git a/runtime/src/sun/compiler/compiler.h b/runtime/src/sun/compiler/compiler.h new file mode 100644 index 0000000..408e198 --- /dev/null +++ b/runtime/src/sun/compiler/compiler.h @@ -0,0 +1,31 @@ +#ifndef SUN_COMPILER_COMPILER_H +#define SUN_COMPILER_COMPILER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*SLCMallocCallback)(void *memory, size_t size); +typedef void (*SLCFreeCallback)(void *memory); + +typedef size_t (*SLCSourceReadCallback)(char *out, size_t outSize, void *userParam); + +struct SLCCompileConfiguration { + SLCMallocCallback realloc; + SLCFreeCallback free; + + SLCSourceReadCallback sourceReadCallback; + void *sourceUserParam; +}; +typedef struct SLCCompileConfiguration SLCCompileConfiguration; + +extern SVMModule *slcCompileSource(const SLCCompileConfiguration *configuration); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/compiler/compiler_internal.h b/runtime/src/sun/compiler/compiler_internal.h new file mode 100644 index 0000000..07036d1 --- /dev/null +++ b/runtime/src/sun/compiler/compiler_internal.h @@ -0,0 +1,20 @@ +#ifndef SUN_COMPILER_COMPILER_INTERNAL_H +#define SUN_COMPILER_COMPILER_INTERNAL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct SLCLexerExtra { + SLCSourceReadCallback readCallback; + void *readCallbackParameter; +}; +typedef struct SLCLexerExtra SLCLexerExtra; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/compiler/sun.l b/runtime/src/sun/compiler/sun.l new file mode 100644 index 0000000..c519809 --- /dev/null +++ b/runtime/src/sun/compiler/sun.l @@ -0,0 +1,100 @@ +%{ + #define YYSTYPE SLTNode * + #define YY_USER_ACTION yyadvancelocation(yylloc, yyleng, yytext); + + #include + #include + #include "sun_parser.h" + + #include + #include + + static void yyadvancelocation(YYLTYPE *location, long length, const char *text); + + #define YY_INPUT(buf, result, max_size) result = yyextra->readCallback(buf, max_size, yyextra->readCallbackParameter); + + //#define YY_DECL int yylex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner, SunSourceReadCallback readCallback) +%} + +%option bison-bridge +%option bison-locations +%option never-interactive +%option noyywrap +%option nounput +%option noinput +%option reentrant +%option extra-type="SLCLexerExtra *" + +%x SL_COMMENT +%x ML_COMMENT + +%% + +"//" { BEGIN(SL_COMMENT); } +\n { BEGIN(INITIAL); } +. ; /* Eat comments */ + +"/*" { BEGIN(ML_COMMENT); } +"*/" { BEGIN(INITIAL); } +\n ; /* Eat comments */ +. ; /* Eat comments */ + +[ \t\n] ; /* Eat whitespace */ + +"if" { return IF; } +"else" { return ELSE; } +"for" { return FOR; } +"do" { return DO; } +"while" { return WHILE; } +"break" { return BREAK; } +"struct" { return TYPE; } + +"return" { return RETURN; } +"sleep" { return SLEEP; } + +"false" { *yylval = sltNodeMakeBoolean(false); return BOOL_FALSE; } +"true" { *yylval = sltNodeMakeBoolean(true); return BOOL_TRUE; } + +"+=" { return ADD_ASSIGN; } +"-=" { return SUBTRACT_ASSIGN; } +"*=" { return MULTIPLY_ASSIGN; } +"/=" { return DIVIDE_ASSIGN; } +"%=" { return MOD_ASSIGN; } + +"&&" { return LOGICAL_AND; } +"||" { return LOGICAL_OR; } + +"==" { return EQUAL; } +"!=" { return NOT_EQUAL; } +"<=" { return LT_EQUAL; } +">=" { return GT_EQUAL; } + + /*"++" { return INCREMENT; } + "--" { return DECREMENT; }*/ + +[0-9]+\.[0-9]+ { *yylval = sltNodeMakeFloat(atof(yytext)); return FLOAT; } +[0-9]+ { *yylval = sltNodeMakeInteger(atoi(yytext)); return INT; } +i[0-9]+ { *yylval = sltNodeMakeRawInteger(atoi(&yytext[1])); return INT; } + +@\"[^\"\n]*\" { *yylval = sltNodeMakeKey(yytext); return STRING; } +\"[^\"\n]*\" { *yylval = sltNodeMakeString(yytext); return STRING; } + +[a-zA-Z0-9_]+ { *yylval = sltNodeMakeIdentifier(yytext); return IDENTIFIER; } + +. { return yytext[0]; } + +%% + +static void yyadvancelocation(YYLTYPE *location, long length, const char *text) { + location->first_column = location->last_column; + location->first_line = location->last_line; + + for (long i = 0; i < length; ++i) { + if (text[i] == '\n') { + ++location->last_line; + location->last_column = 0; + } else { + ++location->last_column; + } + } +} diff --git a/runtime/src/sun/compiler/sun.y b/runtime/src/sun/compiler/sun.y new file mode 100644 index 0000000..b71f4de --- /dev/null +++ b/runtime/src/sun/compiler/sun.y @@ -0,0 +1,465 @@ +%{ + #define YYSTYPE SLTNode * + + #include + #include + + #include "sun_parser.h" + #include "sun_lexer.h" + + void yyerror(const YYLTYPE *location, SLTNode **moduleOut, yyscan_t *scanner, const char *error); +%} + +%pure-parser + +%parse-param {SLTNode **moduleOut} +%parse-param {yyscan_t *scanner} + +%lex-param {yyscan_t *scanner} + +%error-verbose +%locations + +%token IF "if" +%token ELSE "else" +%token FOR "for" +%token DO "do" +%token WHILE "while" +%token BREAK "break" +%token TYPE "struct" + +%token RETURN "return" +%token SLEEP "sleep" + +%token BOOL_FALSE "false" +%token BOOL_TRUE "true" + +%token ADD_ASSIGN "+=" +%token SUBTRACT_ASSIGN "-=" +%token MULTIPLY_ASSIGN "*=" +%token DIVIDE_ASSIGN "/=" +%token MOD_ASSIGN "%=" + +%token LOGICAL_AND "&&" +%token LOGICAL_OR "||" + +%token EQUAL "==" +%token NOT_EQUAL "!=" +%token LT_EQUAL "<=" +%token GT_EQUAL ">=" + + /*%token INCREMENT "++" + %token DECREMENT "--"*/ + +%token IDENTIFIER + +%token INT +%token FLOAT +%token STRING + + /* https://en.cppreference.com/w/c/language/operator_precedence */ +%left ',' +%right '=' "+=" "-=" "*=" "/=" "%=" /* etc... */ +%left "||" +%left "&&" +%left '|' +%left '^' +%left '&' +%left "==" "!=" +%left '<' "<=" '>' ">=" + /* %left "<<" ">>" */ +%left '+' '-' +%left '*' '/' '%' +%right U_PLUS U_MINUS '!' '~' + /* %right "++" "--" "" */ + /* %left "++" "--" "" */ + +%start module + +%% + +module + : optional_statements_or_definitions { + $$ = sltNodeMakeModule($1); + *moduleOut = $$; + } + ; + +optional_statements_or_definitions + : /* Nothing */ { + $$ = NULL; + } + | statements_or_definitions + ; + +statements_or_definitions + : definition { + $$ = sltNodeMakeSequence(NULL, $1); + } + | statement { + $$ = sltNodeMakeSequence(NULL, $1); + } + | statements_or_definitions definition { + $$ = sltNodeMakeSequence($1, $2); + } + | statements_or_definitions statement { + $$ = sltNodeMakeSequence($1, $2); + } + ; + +definition + : function_definition + /*| type_definition*/ + | variable_definition ';' + ; + +function_definition + : IDENTIFIER IDENTIFIER '(' optional_parameter_definitions ')' '{' optional_statements '}' { + $$ = sltNodeMakeFunctionDefinition($1, $2, $4, $7); + } + ; + +optional_parameter_definitions + : /* Nothing */ { + $$ = NULL; + } + | parameter_definitions + ; + +parameter_definitions + : parameter_definition { + $$ = sltNodeMakeSequence(NULL, $1); + } + | parameter_definitions ',' parameter_definition { + $$ = sltNodeMakeSequence($1, $3); + } + ; + +parameter_definition + : IDENTIFIER IDENTIFIER { + $$ = sltNodeMakeFunctionParameterDefinition($1, $2); + } + ; + +/*type_definition + : "struct" IDENTIFIER '{' type_member_definitions '}' { + $$ = sltNodeMakeTypeDefinition($2, $4); + } + ; + +type_member_definitions + : type_member_definition ';' { + $$ = sltNodeMakeSequence(NULL, $1); + } + | type_member_definitions type_member_definition ';' { + $$ = sltNodeMakeSequence($1, $2); + } + ; + +type_member_definition + : IDENTIFIER IDENTIFIER { + $$ = sltNodeMakeTypeMemberDefinition($1, $2); + } + ;*/ + +variable_definition + : IDENTIFIER IDENTIFIER { + $$ = sltNodeMakeVariableDefinition($1, $2, NULL); + } + | IDENTIFIER IDENTIFIER '=' expression { + $$ = sltNodeMakeVariableDefinition($1, $2, $4); + } + ; + +optional_statements + : /* nothing */ { + $$ = NULL; + } + | statements + ; + +statements + : statement { + if ($1 != NULL) { + $$ = sltNodeMakeSequence(NULL, $1); + } + + } + | statements statement { + if ($2 != NULL) { + $$ = sltNodeMakeSequence($1, $2); + } else { + $$ = $1; + } + } + ; + +statement + : ';' { + $$ = NULL; /* Otherwise this will pass up the ';' character */ + } + | variable_definition ';' + | "return" optional_expression ';' { + $$ = sltNodeMakeReturn($2); + } + | "sleep" ';' { + $$ = sltNodeMakeSleep(); + } + | selection_statement + | iteration_statement + | "break" ';' { + $$ = sltNodeMakeBreak(); + } + | expression ';' + | '{' optional_statements '}' { + if ($2 != NULL) { + $$ = sltNodeMakeStatementBlock($2); + } else { + $$ = NULL; + } + } + ; + +selection_statement + : "if" '(' expression ')' statement { + $$ = sltNodeMakeSelection($3, $5, NULL); + } + | "if" '(' expression ')' statement "else" statement { + $$ = sltNodeMakeSelection($3, $5, $7); + } + ; + +iteration_statement + : "for" '(' optional_expression_or_variable_definition ';' optional_expression ';' optional_expression ')' statement { + $$ = sltNodeMakeForIteration($3, $5, $7, $9); + } + | "while" '(' expression ')' statement { + $$ = sltNodeMakeWhileIteration($3, $5); + } + | "do" statement "while" '(' expression ')' ';' { + $$ = sltNodeMakeDoIteration($5, $2); + } + ; + +optional_expression_or_variable_definition + : /* nothing */ { + $$ = NULL; + } + | expression + | variable_definition + ; + +optional_expression + : /* nothing */ { + $$ = NULL; + } + | expression + ; + +expression + : assignment_expression + ; + +assignment_expression + : logic_expression + | unary_expression assignment_operator assignment_expression { + $$ = sltNodeMakeAssignment($1, ($2 == NULL) ? $3 : sltNodeMakeBinaryOperation($2, $1, $3)); + } + ; + +assignment_operator + : '=' { + $$ = NULL; + } + | "+=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeAdd); + } + | "-=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeSubtract); + } + | "*=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeMultiply); + } + | "/=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeDivide); + } + | "%=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeModulo); + } + ; + +logic_expression + : bit_logic_expression + | logic_expression logic_operator bit_logic_expression { + $$ = sltNodeMakeBinaryOperation($2, $1, $3); + } + ; + +logic_operator + : "&&" { + $$ = sltNodeMakeOperator(SLTOperatorTypeLogicalAnd); + } + | "||" { + $$ = sltNodeMakeOperator(SLTOperatorTypeLogicalOr); + } + ; + +bit_logic_expression + : equality_expression + | bit_logic_expression bit_logic_operator equality_expression { + $$ = sltNodeMakeBinaryOperation($2, $1, $3); + } + ; + +bit_logic_operator + : '&' { + $$ = sltNodeMakeOperator(SLTOperatorTypeBitwiseAnd); + } + | '|' { + $$ = sltNodeMakeOperator(SLTOperatorTypeBitwiseOr); + } + | '^' { + $$ = sltNodeMakeOperator(SLTOperatorTypeBitwiseXor); + } + ; + +equality_expression + : arithmetic_expression + | equality_expression equality_operator arithmetic_expression { + $$ = sltNodeMakeBinaryOperation($2, $1, $3); + } + ; + +equality_operator + : "==" { + $$ = sltNodeMakeOperator(SLTOperatorTypeEqual); + } + | "!=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeNotEqual); + } + | "<=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeLessThanEqual); + } + | ">=" { + $$ = sltNodeMakeOperator(SLTOperatorTypeGreaterThanEqual); + } + | '<' { + $$ = sltNodeMakeOperator(SLTOperatorTypeLessThan); + } + | '>' { + $$ = sltNodeMakeOperator(SLTOperatorTypeGreaterThan); + } + ; + +arithmetic_expression + : unary_expression + | arithmetic_expression '+' arithmetic_expression { + $$ = sltNodeMakeBinaryOperation(sltNodeMakeOperator(SLTOperatorTypeAdd), $1, $3); + } + | arithmetic_expression '-' arithmetic_expression { + $$ = sltNodeMakeBinaryOperation(sltNodeMakeOperator(SLTOperatorTypeSubtract), $1, $3); + } + | arithmetic_expression '*' arithmetic_expression { + $$ = sltNodeMakeBinaryOperation(sltNodeMakeOperator(SLTOperatorTypeMultiply), $1, $3); + } + | arithmetic_expression '/' arithmetic_expression { + $$ = sltNodeMakeBinaryOperation(sltNodeMakeOperator(SLTOperatorTypeDivide), $1, $3); + } + | arithmetic_expression '%' arithmetic_expression { + $$ = sltNodeMakeBinaryOperation(sltNodeMakeOperator(SLTOperatorTypeModulo), $1, $3); + } + ; + +unary_expression + : postfix_expression + | '-' %prec U_MINUS unary_expression { + $$ = sltNodeMakeUnaryOperation(sltNodeMakeOperator(SLTOperatorTypeNegative), $2); + } + | '~' unary_expression { + $$ = sltNodeMakeUnaryOperation(sltNodeMakeOperator(SLTOperatorTypeBitwiseNot), $2); + } + | '!' unary_expression { + $$ = sltNodeMakeUnaryOperation(sltNodeMakeOperator(SLTOperatorTypeLogicalNot), $2); + } + ; + +/*unary_operator + : "++" { + $$ = sltNodeMakeOperator(SLTOperatorTypePreIncrement); + } + | "--" { + $$ = sltNodeMakeOperator(SLTOperatorTypePreDecrement); + } + |'+' { + $$ = sltNodeMakeOperator(SLTOperatorTypePositive); + } + | '-' %prec U_MINUS { + $$ = sltNodeMakeOperator(SLTOperatorTypeNegative); + } + | '~' { + $$ = sltNodeMakeOperator(SLTOperatorTypeBitwiseNot); + } + | '!' { + $$ = sltNodeMakeOperator(SLTOperatorTypeLogicalNot); + } + ;*/ + +postfix_expression + : primary_expression + | postfix_expression '[' expression ']' { + $$ = sltNodeMakeArrayAccess($1, $3); + } + | postfix_expression '(' optional_arguments ')' { + $$ = sltNodeMakeFunctionCall($1, $3); + } + | postfix_expression '.' IDENTIFIER { + $$ = sltNodeMakeTypeAccess($1, $3); + } + /*| postfix_expression postfix_unary_operator { + $$ = sltNodeMakeUnaryOperation($1, $2); + }*/ + ; + +/*postfix_unary_operator + : "++" { + $$ = sltNodeMakeOperator(SLTOperatorTypePostIncrement); + } + | "--" { + $$ = sltNodeMakeOperator(SLTOperatorTypePostDecrement); + } + ;*/ + +optional_arguments + : /* nothing */ { + $$ = NULL; + } + | arguments + ; + +arguments + : expression { + $$ = sltNodeMakeSequence(NULL, sltNodeMakeArgument($1)); + } + | arguments ',' expression { + $$ = sltNodeMakeSequence($1, sltNodeMakeArgument($3)); + } + ; + +primary_expression + : IDENTIFIER + | BOOL_FALSE + | BOOL_TRUE + | INT + | FLOAT + | STRING + | '(' expression ')' { + $$ = sltNodeMakeCompound($2); + } + ; + +%% + +void yyerror(const YYLTYPE *location, SLTNode **moduleOut, yyscan_t *scanner, const char *error) { +//void yyerror(const YYLTYPE *location, yyscan_t scanner, const char *error) { + printf("[ERROR] Line #%u, Characters %u: %s\n", /*yyget_lineno(scanner)*/location->first_line, /*yyget_column(scanner)*/location->first_column, error); +} diff --git a/runtime/src/sun/compiler/vm_generator.c b/runtime/src/sun/compiler/vm_generator.c new file mode 100644 index 0000000..deb10b8 --- /dev/null +++ b/runtime/src/sun/compiler/vm_generator.c @@ -0,0 +1,1117 @@ +#include "vm_generator.h" + +#include +#include +#include +#include +#include + + +#include //fixme +#include //fixme +#include //fixme +#include //fixme +#include //fixme + +#define generator_assert_msg(t,m,...) if(!(t)) { fprintf(stderr,"%s:%u ERROR:"m"\n",__FILE__,__LINE__, ##__VA_ARGS__); exit(1); } +#define generator_assert(t) generator_assert_msg(t,"invalid") + +struct VMGeneratorInstruction { + SVMInstruction instruction; +}; + +struct VMGeneratorOutputScope { + char *stringClump; + size_t stringClumpSize; + size_t stringClumpMaxSize; + + struct VMGeneratorInstruction *instructions; + size_t instructionCount; + SVMPointer nextInstructionIdx; + + struct VMGeneratorInstruction *resolvableDefinition; +}; +typedef struct VMGeneratorOutputScope VMGeneratorOutputScope; + +enum VMNodeMetadataIdentifierType { + VMNodeMetadataIdentifierTypeUnknown, + VMNodeMetadataIdentifierTypeNullType, + VMNodeMetadataIdentifierTypeIntegerType, + VMNodeMetadataIdentifierTypeFloatType, + VMNodeMetadataIdentifierTypeStringType, + //VMNodeMetadataIdentifierTypeUserType, + VMNodeMetadataIdentifierTypeVariable, + VMNodeMetadataIdentifierTypeFunction, + VMNodeMetadataIdentifierTypeParameter, +}; +typedef enum VMNodeMetadataIdentifierType VMNodeMetadataIdentifierType; + +struct VMNodeMetadata { + struct { + bool definesScope; + bool holdsVariableScope; + SLTNode *parentScope; + SLTNode *scopedFunctionsHead; + SLTNode *scopedVariablesHead; + SLTNode *scopedParametersHead; + SLTNode *scopedBreaksHead; + } scope; + + struct { + SVMPointer address; + SLTNode *scopedFunctionNext; + } function; + + struct { + SLTNode *scopedVariableNext; + } variable; + + struct { + SLTNode *scopedParameterNext; + } parameter; + + struct { + SVMPointer breakInstruction; + SLTNode *scopedBreakNext; + } breakStatement; + + struct { + VMNodeMetadataIdentifierType type; + SLTNode *resolvedNode; + } identifier; + + struct { + SVMStackOffset offset; + } stack; + + struct { + SVMPointer address; + } string; + + struct { + bool native; + SVMPointer instruction; + } functionCall; +}; +typedef struct VMNodeMetadata VMNodeMetadata; + +union VMGeneratorVisitor { + VMGeneratorOutputScope *generator; + SLTNode *currentScope; + struct { + bool typeChanged; + bool typeUnresolved; + }; +}; +typedef union VMGeneratorVisitor VMGeneratorVisitor; + + +#define sltGetNodeMetadata(node) ((VMNodeMetadata *)(node)->metadata) + + + +static VMGeneratorOutputScope *generatorCreate() { + VMGeneratorOutputScope *scope = malloc(sizeof(VMGeneratorOutputScope)); // fixme these mallocs + memset(scope, 0, sizeof(VMGeneratorOutputScope)); + + scope->instructionCount = 1024; + scope->instructions = malloc(scope->instructionCount * sizeof(struct VMGeneratorInstruction)); + scope->nextInstructionIdx = 0; + + scope->stringClumpMaxSize = 1024; + scope->stringClump = malloc(scope->stringClumpMaxSize); + scope->stringClumpSize = 0; + + return scope; +} + + + +static size_t opcodeOperandCount(SVMOpcode opcode) { + switch (opcode) { + case SVMOpcodeSLEEP: + case SVMOpcodePOPJUMP: + return 0; + + case SVMOpcodeSTK: + case SVMOpcodeJUMP: + case SVMOpcodePUSHJUMP: + return 1; + + case SVMOpcodeMOV: + case SVMOpcodeSET: + case SVMOpcodeINV: + case SVMOpcodeBNOT: + case SVMOpcodeNOT: + case SVMOpcodeJT: + case SVMOpcodeCALL: + return 2; + + case SVMOpcodeADD: + case SVMOpcodeSUB: + case SVMOpcodeMUL: + case SVMOpcodeDIV: + case SVMOpcodeMOD: + case SVMOpcodeBAND: + case SVMOpcodeBOR: + case SVMOpcodeBXOR: + case SVMOpcodeAND: + case SVMOpcodeOR: + case SVMOpcodeEQ: + case SVMOpcodeNEQ: + case SVMOpcodeLT: + case SVMOpcodeLTEQ: + case SVMOpcodeGT: + case SVMOpcodeGTEQ: + return 3; + + default: + generator_assert_msg(false, "invalid opcode %u", opcode); + return -1; + } +} + + +static SVMPointer generatorNextInstruction(VMGeneratorOutputScope *generator) { + generator_assert(generator->nextInstructionIdx < generator->instructionCount); + SVMPointer idx = generator->nextInstructionIdx; + return idx; +} + +static SVMPointer generatorAddInstruction(VMGeneratorOutputScope *generator, SVMOpcode opcode, ...) { + generator_assert(generator->nextInstructionIdx < generator->instructionCount); + + SVMPointer idx = generatorNextInstruction(generator); + generator->nextInstructionIdx++; + struct VMGeneratorInstruction *instruction = &generator->instructions[idx]; + + instruction->instruction.opcode = opcode; + + size_t numOperands = opcodeOperandCount(opcode); + + va_list args; + va_start(args, opcode); + for (size_t i = 0; i < numOperands; ++i) { + instruction->instruction.operands[i] = va_arg(args, SVMOperand); + } + va_end(args); + + return idx; +} + +static void generatorPatchOperand(VMGeneratorOutputScope *generator, SVMPointer instruction, size_t idx, SVMOperand value) { + generator_assert(instruction < generator->instructionCount); + generator_assert_msg(idx < opcodeOperandCount(generator->instructions[instruction].instruction.opcode), "invalid idx"); + generator->instructions[instruction].instruction.operands[idx] = value; +} + +static SVMPointer generatorAddString(VMGeneratorOutputScope *generator, const char *string) { + char *ptr = generator->stringClump; + + while (ptr < generator->stringClump + generator->stringClumpSize) { + //printf("testing string: %s == %s\n", ptr, string); + if (strcmp(string, ptr) == 0) { + return ptr - generator->stringClump; + } + ptr+=strlen(ptr) + 1; + } + + size_t stringLength = strlen(string) + 1; + generator_assert_msg(ptr + stringLength <= generator->stringClump + generator->stringClumpMaxSize, "out of string space!!!"); + + strcpy(ptr, string); + generator->stringClumpSize += stringLength; + + //printf("added string: %s\n", string); + + return ptr - generator->stringClump; +} + +static SVMStackOffset generatorResolveIdentifier(VMGeneratorOutputScope *generator, SLTNode *node) { + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + generator_assert_msg(metadata->identifier.type != VMNodeMetadataIdentifierTypeUnknown, "could not resolve %s", node->identifierStringValue); + SVMStackOffset offset = sltGetNodeMetadata(metadata->identifier.resolvedNode)->stack.offset; + return offset; +} + + +static SVMModule *generatorFinalize(VMGeneratorOutputScope *generator) { + size_t memorySize = sizeof(SVMModule) + generator->stringClumpSize + /*0 * sizeof(SVMModuleFunctionDetails) +*/ generator->nextInstructionIdx * sizeof(SVMInstruction); + + SVMModule *module = (SVMModule *)malloc(memorySize); + module->header[0] = 's'; + module->header[1] = 'u'; + module->header[2] = 'n'; + module->header[3] = 'l'; + module->magic = 1525; + module->stringBlobLength = generator->stringClumpSize; + module->numFunctions = 0; // FIXME + module->numInstructions = generator->nextInstructionIdx; + + memcpy((void *)module + sizeof(SVMModule), generator->stringClump, module->stringBlobLength); + // COPY FUNCTIONS HERE... + memcpy((void *)module + sizeof(SVMModule) + module->stringBlobLength, generator->instructions, module->numInstructions * sizeof(SVMInstruction)); + + return module; +} + + + + +static void addNodeMetadata(SLTNode *node, void *userParameter) { + VMNodeMetadata *metadata = (VMNodeMetadata *)malloc(sizeof(VMNodeMetadata));// fixme + memset(metadata, 0, sizeof(VMNodeMetadata)); + node->metadata = metadata; +} + + +static void findStrings(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeString: + metadata->string.address = generatorAddString(visitor->generator, node->stringValue); + break; + + case SLTNodeTypeFunctionCall: + metadata->string.address = generatorAddString(visitor->generator, node->functionCallFunction->identifierStringValue); + break; + + default: + /* do nothing */ + break; + } +} + +static bool nodeTypeDefinesScope(SLTNodeType type) { + switch (type) { + case SLTNodeTypeModule: + case SLTNodeTypeFunctionDefinition: + case SLTNodeTypeTypeDefinition: + case SLTNodeTypeForIteration: + case SLTNodeTypeDoIteration: + case SLTNodeTypeWhileIteration: + case SLTNodeTypeStatementBlock: + return true; + + default: + return false; + } +} + +static bool nodeTypeHoldsVariables(SLTNodeType type) { + switch (type) { + case SLTNodeTypeModule: + case SLTNodeTypeFunctionDefinition: + return true; + + default: + return false; + } +} + +static void beginScopeNode(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + metadata->scope.parentScope = visitor->currentScope; + + if (nodeTypeDefinesScope(node->type)) { + metadata->scope.definesScope = true; + metadata->scope.holdsVariableScope = nodeTypeHoldsVariables(node->type); + visitor->currentScope = node; + } +} + +static void endScopeNode(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + if (nodeTypeDefinesScope(node->type)) { + visitor->currentScope = metadata->scope.parentScope; + } +} + +static SLTNode *findScope(SLTNode *node) { + while (sltGetNodeMetadata(node)->scope.definesScope == false) { + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + node = metadata->scope.parentScope; + generator_assert_msg(node != NULL, "failed to scope"); // FIXME + } + + return node; +} + +static SLTNode *findContainingScope(SLTNode *node) { + for (;;) { + node = findScope(node); + + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + if (metadata->scope.holdsVariableScope) { + return node; + } + + node = metadata->scope.parentScope; + + generator_assert_msg(node != NULL, "failed to scope"); // FIXME + } +} + +static void scopeDefinitions(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeFunctionParameterDefinition: { + //printf("def parameter %s\n", node->functionParameterDefinitionIdentifier->stringValue); + VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findContainingScope(node)); + metadata->parameter.scopedParameterNext = scopeMetadata->scope.scopedParametersHead; + scopeMetadata->scope.scopedParametersHead = node; + break; + } + + case SLTNodeTypeVariableDefinition: { + //printf("def var %s\n", node->variableDefinitionIdentifier->stringValue); + VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findContainingScope(node)); + metadata->variable.scopedVariableNext = scopeMetadata->scope.scopedVariablesHead; + scopeMetadata->scope.scopedVariablesHead = node; + break; + } + + case SLTNodeTypeFunctionDefinition: { + //printf("def func %s\n", node->functionDefinitionIdentifier->stringValue); + VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findScope((sltGetNodeMetadata(findScope(node))->scope.parentScope))); // Functions define a scope... + metadata->function.scopedFunctionNext = scopeMetadata->scope.scopedFunctionsHead; + scopeMetadata->scope.scopedFunctionsHead = node; + break; + } + + default: + break; + } +} + +static SLTNode *resolveDefinition(VMNodeMetadataIdentifierType *typeOut, SLTNode *node, const char *name) { + if (strcmp(name, "void") == 0) { // FIXME, can de-duplicate these for speed earlier.. + *typeOut = VMNodeMetadataIdentifierTypeNullType; + return NULL; + } + + if (strcmp(name, "int") == 0) { + *typeOut = VMNodeMetadataIdentifierTypeIntegerType; + return NULL; + } + + if (strcmp(name, "float") == 0) { + *typeOut = VMNodeMetadataIdentifierTypeFloatType; + return NULL; + } + + if (strcmp(name, "string") == 0) { + *typeOut = VMNodeMetadataIdentifierTypeStringType; + return NULL; + } + + for (;;) { + VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findScope(node)); + + // Should do types here... + + for (SLTNode *n = scopeMetadata->scope.scopedFunctionsHead; n != NULL; n = sltGetNodeMetadata(n)->function.scopedFunctionNext) { + if (strcmp(n->functionDefinitionIdentifier->identifierStringValue, name) == 0) { + *typeOut = VMNodeMetadataIdentifierTypeFunction; + //printf("GOT F %s\n", name); + return n; + } + } + + for (SLTNode *n = scopeMetadata->scope.scopedVariablesHead; n != NULL; n = sltGetNodeMetadata(n)->variable.scopedVariableNext) { + if (strcmp(n->variableDefinitionIdentifier->identifierStringValue, name) == 0) { + *typeOut = VMNodeMetadataIdentifierTypeVariable; + //printf("GOT V %s\n", name); + return n; + } + } + + for (SLTNode *n = scopeMetadata->scope.scopedParametersHead; n != NULL; n = sltGetNodeMetadata(n)->parameter.scopedParameterNext) { + if (strcmp(n->functionParameterDefinitionIdentifier->identifierStringValue, name) == 0) { + *typeOut = VMNodeMetadataIdentifierTypeParameter; + //printf("GOT P %s\n", name); + return n; + } + } + + if (scopeMetadata->scope.parentScope != NULL) { + node = scopeMetadata->scope.parentScope; + } else { + break; + } + } + + return NULL; +} + +static void resolveDefinitions(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeIdentifier: + metadata->identifier.resolvedNode = resolveDefinition(&metadata->identifier.type, node, node->identifierStringValue); + //printf("trying to get %s %x\n", node->stringValue, metadata->identifier.resolvedNode); + //metadata->variable.scopedVariableNext = metadata->scope.scopedVariablesHead; + //metadata->scope.scopedVariablesHead = node; + break; + + default: + break; + } +} + +static void resolveDefinitionsNativeFunctions(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeFunctionCall: + if (sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode == NULL) { + metadata->functionCall.instruction = node->functionCallFunction->identifierStringKeyValue; + metadata->functionCall.native = true; + } + + default: + break; + } +} + + + +static void indexDefinitions(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + // Functions put their return value at the 0th stack position, modules start at -1 + size_t idx = 1; + + size_t parameterCount = 0; + for (SLTNode *parameter = metadata->scope.scopedParametersHead; parameter != NULL; ++parameterCount, parameter = sltGetNodeMetadata(parameter)->parameter.scopedParameterNext); + + SLTNode *parameter = metadata->scope.scopedParametersHead; + while (parameter != NULL) { + sltGetNodeMetadata(parameter)->stack.offset = node->type == SLTNodeTypeModule ? -idx : (parameterCount + 1) - idx; // Parameter positions are inverted... + ++idx; + parameter = sltGetNodeMetadata(parameter)->parameter.scopedParameterNext; + } + + SLTNode *variable = metadata->scope.scopedVariablesHead; + while (variable != NULL) { + sltGetNodeMetadata(variable)->stack.offset = node->type == SLTNodeTypeModule ? -idx : idx; + ++idx; + variable = sltGetNodeMetadata(variable)->variable.scopedVariableNext; + } +} + + + +/*static void resolveTypes(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeUnknown: + case SLTNodeTypeSequence: + generator_assert_msg(false, "unexpected: %s", sltNodeToString(node));// fixme + break; + + case SLTNodeTypeIdentifier: + // ...?? + + case SLTNodeTypeBoolean: + case SLTNodeTypeInteger: + case SLTNodeTypeFloat: + case SLTNodeTypeString: + + case SLTNodeTypeCompound: + + case SLTNodeTypeArgument: + + case SLTNodeTypeArrayAccess: + case SLTNodeTypeTypeAccess: + + case SLTNodeTypeFunctionCall: + + case SLTNodeTypeUnaryOperation: + case SLTNodeTypeBinaryOperation: + + case SLTNodeTypeOperator: + + case SLTNodeTypeAssignment: + + case SLTNodeTypeReturn: + case SLTNodeTypeSleep: + + case SLTNodeTypeForIteration: + case SLTNodeTypeDoIteration: + case SLTNodeTypeWhileIteration: + + case SLTNodeTypeSelection: + + case SLTNodeTypeStatementBlock: + + case SLTNodeTypeVariableDefinition: + + case SLTNodeTypeTypeDefinition: + case SLTNodeTypeTypeMemberDefinition: + + case SLTNodeTypeFunctionDefinition: + case SLTNodeTypeFunctionParameterDefinition: + + case SLTNodeTypeModule: + + + } + +visitor.typeChanged = false; + + + + + + + if (node->dataType == SLTDataTypeUnknown) { + visitor->typeUnresolved = true; + } +}*/ + +static bool nodeTypeIsLoop(SLTNodeType type) { + switch (type) { + case SLTNodeTypeForIteration: + case SLTNodeTypeDoIteration: + case SLTNodeTypeWhileIteration: + return true; + + default: + return false; + } +} + +static SLTNode *findLoopScope(SLTNode *node) { + for (;;) { + node = findScope(node); + + if (nodeTypeIsLoop(node->type)) { + return node; + } + + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + node = metadata->scope.parentScope; + + generator_assert_msg(node != NULL, "failed to scope loop"); // FIXME + } +} + +static void scopeIterationBreaks(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeBreak: { + VMNodeMetadata *scopeMetadata = sltGetNodeMetadata(findLoopScope(node)); + metadata->breakStatement.scopedBreakNext = scopeMetadata->scope.scopedBreaksHead; + scopeMetadata->scope.scopedBreaksHead = node; + break; + } + + default: + break; + } +} + + +static SVMPointer generateValueInstructions(VMGeneratorOutputScope *generator, SLTNode *node, SVMOperand target) { + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeIdentifier: { + SVMOperand source = { .stackOffset = generatorResolveIdentifier(generator, node) }; + return generatorAddInstruction(generator, SVMOpcodeMOV, target, source); + } + + case SLTNodeTypeBoolean: { + SVMOperand source = { .integerLiteral = node->booleanValue ? 1 : 0 }; + return generatorAddInstruction(generator, SVMOpcodeSET, target, source); + } + + case SLTNodeTypeInteger: { + SVMOperand source = { .integerLiteral = FIXED(node->integerValue) }; + return generatorAddInstruction(generator, SVMOpcodeSET, target, source); + } + + case SLTNodeTypeRawInteger: { + SVMOperand source = { .__raw = node->integerValue }; + return generatorAddInstruction(generator, SVMOpcodeSET, target, source); + } + + case SLTNodeTypeFloat: { + SVMOperand source = { .floatLiteral = FIXED_FROM_FLOAT(node->floatValue) }; + return generatorAddInstruction(generator, SVMOpcodeSET, target, source); + } + + case SLTNodeTypeString: { + SVMOperand source = { .pointerLiteral = metadata->string.address }; // FIXME, string pool needed + return generatorAddInstruction(generator, SVMOpcodeSET, target, source); + } + + case SLTNodeTypeKey: { + SVMOperand source = { .pointerLiteral = node->keyValue }; + return generatorAddInstruction(generator, SVMOpcodeSET, target, source); + } + + default: + generator_assert_msg(false, "unexpected: %s", sltNodeToString(node));// fixme + return -1; // FIXME + } +} + +static SVMPointer generateExpressionInstructions(VMGeneratorOutputScope *generator, SLTNode *node, SVMOperand target, SVMStackOffset workingStackOffset) { + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + switch (node->type) { + case SLTNodeTypeBinaryOperation: { + SVMOperand lhsOperand = { .stackOffset = workingStackOffset }; + generateExpressionInstructions(generator, node->binaryOperationLHS, lhsOperand, workingStackOffset + 1); + + SVMOperand rhsOperand = { .stackOffset = workingStackOffset + 1 }; + generateExpressionInstructions(generator, node->binaryOperationRHS, rhsOperand, workingStackOffset + 2); + + switch (node->binaryOperationOperator->operatorType) { + case SLTOperatorTypeAdd: + return generatorAddInstruction(generator, SVMOpcodeADD, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeSubtract: + return generatorAddInstruction(generator, SVMOpcodeSUB, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeMultiply: + return generatorAddInstruction(generator, SVMOpcodeMUL, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeDivide: + return generatorAddInstruction(generator, SVMOpcodeDIV, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeModulo: + return generatorAddInstruction(generator, SVMOpcodeMOD, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeBitwiseAnd: + return generatorAddInstruction(generator, SVMOpcodeBAND, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeBitwiseOr: + return generatorAddInstruction(generator, SVMOpcodeBOR, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeBitwiseXor: + return generatorAddInstruction(generator, SVMOpcodeBXOR, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeLogicalAnd: + return generatorAddInstruction(generator, SVMOpcodeAND, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeLogicalOr: + return generatorAddInstruction(generator, SVMOpcodeOR, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeEqual: + return generatorAddInstruction(generator, SVMOpcodeEQ, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeNotEqual: + return generatorAddInstruction(generator, SVMOpcodeNEQ, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeLessThan: + return generatorAddInstruction(generator, SVMOpcodeLT, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeLessThanEqual: + return generatorAddInstruction(generator, SVMOpcodeLTEQ, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeGreaterThan: + return generatorAddInstruction(generator, SVMOpcodeGT, target, lhsOperand, rhsOperand); + + case SLTOperatorTypeGreaterThanEqual: + return generatorAddInstruction(generator, SVMOpcodeGTEQ, target, lhsOperand, rhsOperand); + + default: + generator_assert_msg(false, "invalid binary operator %s", sltOperatorTypeToString(node->binaryOperationOperator->operatorType)); + return -1; + } + } + + case SLTNodeTypeUnaryOperation: { + SVMOperand operand = { .stackOffset = target.stackOffset }; + generateExpressionInstructions(generator, node->unaryOperationOperand, operand, workingStackOffset); + + switch (node->unaryOperationOperator->operatorType) { + //case SLTOperatorTypePositive: + // return -1; + + case SLTOperatorTypeNegative: + return generatorAddInstruction(generator, SVMOpcodeINV, target, operand); + + case SLTOperatorTypeBitwiseNot: + return generatorAddInstruction(generator, SVMOpcodeBNOT, target, operand); + + case SLTOperatorTypeLogicalNot: + return generatorAddInstruction(generator, SVMOpcodeNOT, target, operand); + + default: + generator_assert_msg(false, "invalid unary operator %s", sltOperatorTypeToString(node->unaryOperationOperator->operatorType)); + return -1; + } + } + + case SLTNodeTypeArrayAccess: + generator_assert_msg(false, "not implemented: %s", sltNodeToString(node)); + return -1; + + case SLTNodeTypeFunctionCall: { + //generator_assert_msg(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode != NULL, "unresolved function: %s", node->functionCallFunction->stringValue);// fixme + + SVMPointer r = generatorNextInstruction(generator); + + SVMInteger parameterCount = 0; + for (SLTNode *n = node->functionCallArguments; n != NULL; n = n->sequenceNext) { + ++parameterCount; + SVMStackOffset parameterTarget = workingStackOffset + parameterCount; + SVMOperand target = { .stackOffset = parameterTarget, }; + generateExpressionInstructions(generator, n->sequenceNode->argumentExpression, target, parameterTarget); + } + + // Offset the stack to make 0 where we're returning into... + SVMStackOffset stackOffset = workingStackOffset;// + parameterCount; + generatorAddInstruction(generator, SVMOpcodeSTK, stackOffset); + + // Call the function + if (metadata->functionCall.native == false) { + metadata->functionCall.instruction = generatorAddInstruction(generator, SVMOpcodePUSHJUMP, 999); // Silly marker, we patch this later... + } else { + metadata->functionCall.instruction = generatorAddInstruction(generator, SVMOpcodeCALL, metadata->functionCall.instruction, parameterCount); + } + + // Put the stack back + generatorAddInstruction(generator, SVMOpcodeSTK, -stackOffset); + + // Move result + if (target.stackOffset != workingStackOffset) { + SVMOperand source = { .stackOffset = workingStackOffset }; + generatorAddInstruction(generator, SVMOpcodeMOV, target, source); + } + + return r; + } + + case SLTNodeTypeTypeAccess: + generator_assert_msg(false, "not implemented: %s", sltNodeToString(node)); + return -1; + + case SLTNodeTypeCompound: + return generateExpressionInstructions(generator, node->compoundSubexpression, target, workingStackOffset); + + default: + return generateValueInstructions(generator, node, target); + } +} + +static SVMPointer generateStatementInstructions(VMGeneratorOutputScope *generator, SLTNode *node, SVMStackOffset workingStackOffset) { + switch (node->type) { + case SLTNodeTypeStatementBlock: { + SVMPointer r = generatorNextInstruction(generator); + + // FIXME, call the function thing... + // FIXME, open some kind of scope?? + for (SLTNode *n = node->statementBlockContents; n != NULL; n = n->sequenceNext) { + generateStatementInstructions(generator, n->sequenceNode, workingStackOffset); + } + + return r; + } + + case SLTNodeTypeVariableDefinition: { + SVMPointer r = generatorNextInstruction(generator); + + if (node->variableDefinitionDefaultExpression != NULL) { + SVMOperand target = { .stackOffset = generatorResolveIdentifier(generator, node->variableDefinitionIdentifier), }; + generateExpressionInstructions(generator, node->variableDefinitionDefaultExpression, target, workingStackOffset); + } + + return r; + } + + case SLTNodeTypeSelection: { + SVMPointer r = generatorNextInstruction(generator); + + SVMOperand valid = { .stackOffset = 0, }; + generateExpressionInstructions(generator, node->selectionValidExpression, valid, workingStackOffset + 1); + generatorAddInstruction(generator, SVMOpcodeNOT, valid, valid); // Inverse for this check... + SVMPointer patchPre = generatorAddInstruction(generator, SVMOpcodeJT, valid, 999); + + if (node->selectionValidStatement != NULL) { + generateStatementInstructions(generator, node->selectionValidStatement, workingStackOffset); + } + + if (node->selectionInvalidStatement != NULL) { + SVMPointer patchPost = generatorAddInstruction(generator, SVMOpcodeJUMP, 999); + + SVMOperand target = { .pointerLiteral = generatorNextInstruction(generator), }; + generatorPatchOperand(generator, patchPre, 1, target); + + generateStatementInstructions(generator, node->selectionInvalidStatement, workingStackOffset); + + target.pointerLiteral = generatorNextInstruction(generator); + generatorPatchOperand(generator, patchPost, 0, target); + } else { + SVMOperand target = { .pointerLiteral = generatorNextInstruction(generator), }; + generatorPatchOperand(generator, patchPre, 1, target); + } + + return r; + } + + case SLTNodeTypeDoIteration: + case SLTNodeTypeForIteration: + case SLTNodeTypeWhileIteration: { + if (node->iterationInitialExpression != NULL) { + //SVMOperand target = { .stackOffset = 0, }; + //generateExpressionInstructions(generator, node->iterationInitialExpression, target, workingStackOffset); // FIXME, is this a statement?? + generateStatementInstructions(generator, node->iterationInitialExpression, workingStackOffset); + } + + SVMPointer r = generatorNextInstruction(generator); + + SVMPointer patchPre; + if (node->iterationPreValidExpression != NULL) { + SVMOperand valid = { .stackOffset = 0, }; + generateExpressionInstructions(generator, node->iterationPreValidExpression, valid, workingStackOffset + 1); + generatorAddInstruction(generator, SVMOpcodeNOT, valid, valid); // Inverse for this check... + patchPre = generatorAddInstruction(generator, SVMOpcodeJT, valid, 999); + } + + if (node->iterationStatement != NULL) { + generateStatementInstructions(generator, node->iterationStatement, workingStackOffset); + } + + if (node->iterationLoopExpression != NULL) { + //SVMOperand target = { .stackOffset = 0, }; + //generateExpressionInstructions(generator, node->iterationLoopExpression, target, workingStackOffset); // FIXME, is this a statement?? + generateStatementInstructions(generator, node->iterationLoopExpression, workingStackOffset); + } + + if (node->iterationPostValidExpression != NULL) { + SVMOperand valid = { .stackOffset = 0, }; + generateExpressionInstructions(generator, node->iterationPostValidExpression, valid, workingStackOffset + 1); + generatorAddInstruction(generator, SVMOpcodeJT, valid, r); + } else { + generatorAddInstruction(generator, SVMOpcodeJUMP, r); + } + + // Patch jump... + SVMOperand target = { .pointerLiteral = generatorNextInstruction(generator), }; + + if (node->iterationPreValidExpression != NULL) { + generatorPatchOperand(generator, patchPre, 1, target); + } + + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + for (SLTNode *v = metadata->scope.scopedBreaksHead; v != NULL; v = sltGetNodeMetadata(v)->breakStatement.scopedBreakNext) { + generatorPatchOperand(generator, sltGetNodeMetadata(v)->breakStatement.breakInstruction, 0, target); + } + + return r; + } + + case SLTNodeTypeAssignment: { + SVMOperand target = { .stackOffset = generatorResolveIdentifier(generator, node->assignmentTarget) }; + return generateExpressionInstructions(generator, node->assignmentSource, target, workingStackOffset); + } + + case SLTNodeTypeReturn: { + SVMPointer r = generatorNextInstruction(generator); + + if (node->returnExpression != NULL) { + SVMOperand target = { .stackOffset = 0, }; // return is always at 0 + generateExpressionInstructions(generator, node->returnExpression, target, workingStackOffset); + } + generatorAddInstruction(generator, SVMOpcodePOPJUMP); + + return r; + } + + case SLTNodeTypeSleep: + return generatorAddInstruction(generator, SVMOpcodeSLEEP); + + case SLTNodeTypeBreak: { + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + metadata->breakStatement.breakInstruction = generatorAddInstruction(generator, SVMOpcodeJUMP, 999); + return metadata->breakStatement.breakInstruction; + } + + default: { +// generator_assert_msg(false, "not implemented as statement: %s", sltNodeToString(node)); + SVMOperand target = { .stackOffset = 0, }; // FIXME!!! + return generateExpressionInstructions(generator, node, target, workingStackOffset); + } + } +} + +static void generateFunctionDefinitionInstructions(VMGeneratorOutputScope *generator, SLTNode *node) { + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + // count parameters, these are first on the stack... + size_t numParameters = 0; + for (SLTNode *p = metadata->scope.scopedParametersHead; p != NULL; ++numParameters, p = sltGetNodeMetadata(p)->parameter.scopedParameterNext); + + // next, count the variables + size_t numVariables = 0; + for (SLTNode *v = metadata->scope.scopedVariablesHead; v != NULL; ++numVariables, v = sltGetNodeMetadata(v)->variable.scopedVariableNext); + + metadata->function.address = generatorNextInstruction(generator); + + SVMStackOffset workingStackOffset = 1 + numParameters + numVariables; + if (node->functionDefinitionBody != NULL) { + generator_assert(node->functionDefinitionBody->type == SLTNodeTypeSequence); + for (SLTNode *n = node->functionDefinitionBody; n != NULL; n = n->sequenceNext) { + generateStatementInstructions(generator, n->sequenceNode, workingStackOffset); + } + } + + // fallback return + generatorAddInstruction(generator, SVMOpcodePOPJUMP); +} + +static size_t generateModuleInstructions(VMGeneratorOutputScope *generator, SLTNode *node) { + generator_assert(node != NULL && node->type == SLTNodeTypeModule); + + if (node->moduleStatementsAndDefinitions != NULL) { + SVMPointer start = generatorAddInstruction(generator, SVMOpcodeJUMP, 999); + + generator_assert(node->moduleStatementsAndDefinitions->type == SLTNodeTypeSequence); + + // do functions first... + for (SLTNode *n = node->moduleStatementsAndDefinitions; n != NULL; n = n->sequenceNext) { + if (n->sequenceNode->type == SLTNodeTypeFunctionDefinition) { + generateFunctionDefinitionInstructions(generator, n->sequenceNode); + } + } + + // Patch to jump to the start... + SVMOperand address = { .pointerLiteral = generatorNextInstruction(generator) }; + generatorPatchOperand(generator, start, 0, address); + + // then do variables + for (SLTNode *n = node->moduleStatementsAndDefinitions; n != NULL; n = n->sequenceNext) { + switch (n->sequenceNode->type) { + case SLTNodeTypeFunctionDefinition: + // Do nothing... + break; + + case SLTNodeTypeVariableDefinition: + generateStatementInstructions(generator, n->sequenceNode, 0); + break; + + default: + //generator_assert_msg(false, "could not define %s", sltNodeTypeToString(n->sequenceNode->type)); + break; + } + } + + // statements + for (SLTNode *n = node->moduleStatementsAndDefinitions; n != NULL; n = n->sequenceNext) { + switch (n->sequenceNode->type) { + case SLTNodeTypeVariableDefinition: + case SLTNodeTypeTypeDefinition: + case SLTNodeTypeFunctionDefinition: + // Do nothing... + break; + + default: + generateStatementInstructions(generator, n->sequenceNode, 0); + break; + } + } + } + + return 0; +} + + + + +static void patchFunctionCalls(SLTNode *node, void *userParameter) { + VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter; + VMNodeMetadata *metadata = sltGetNodeMetadata(node); + + if (node->type == SLTNodeTypeFunctionCall) { + if (metadata->functionCall.native == false) { + generator_assert_msg(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode->type == SLTNodeTypeFunctionDefinition, "%s", sltNodeToString(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode)); + SVMOperand operand = { .pointerLiteral = sltGetNodeMetadata(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode)->function.address }; + generatorPatchOperand(visitor->generator, metadata->functionCall.instruction, 0, operand); + } + } +} + + + +SVMModule *slcGenerateVMInstructions(SLTNode *moduleNode) { + VMGeneratorOutputScope *generator = generatorCreate(); + + VMGeneratorVisitor visitor; + + sltTreeIterate(moduleNode, addNodeMetadata, NULL, NULL); + + visitor.generator = generator; + sltTreeIterate(moduleNode, findStrings, NULL, &visitor); + + visitor.currentScope = NULL; + sltTreeIterate(moduleNode, beginScopeNode, endScopeNode, &visitor); + + visitor.generator = generator; + sltTreeIterate(moduleNode, scopeDefinitions, NULL, &visitor); + sltTreeIterate(moduleNode, resolveDefinitions, resolveDefinitionsNativeFunctions, &visitor); + sltTreeIterate(moduleNode, indexDefinitions, NULL, &visitor); + + sltTreeIterate(moduleNode, scopeIterationBreaks, NULL, &visitor); + + /*do { + visitor.typeUnresolved = false; + visitor.typeChanged = false; + sltTreeIterate(moduleNode, resolveTypes, NULL, &visitor); + } while (visitor.typeUnresolved && visitor.typeChanged);*/ + + generateModuleInstructions(generator, moduleNode); + + visitor.generator = generator; + sltTreeIterate(moduleNode, patchFunctionCalls, NULL, &visitor); + + + SVMModule *module = generatorFinalize(generator); + + + /*for (size_t i = 0; i < generator->nextInstructionIdx; ++i) { + SVMOpcode opcode = generator->instructions[i].instruction.opcode; + switch (opcodeOperandCount(opcode)) { + case 0: + default: + printf("%u : %s\n", i, svmOpcodeToString(opcode)); + break; + + case 1: + printf("%u : %s %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset); + break; + + case 2: + printf("%u : %s %d %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset, generator->instructions[i].instruction.p1.stackOffset); + break; + + case 3: + printf("%u : %s %d %d %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset, generator->instructions[i].instruction.p1.stackOffset, generator->instructions[i].instruction.p2.stackOffset); + break; + } + }*/ + + //fix references... + + return module; +} diff --git a/runtime/src/sun/compiler/vm_generator.h b/runtime/src/sun/compiler/vm_generator.h new file mode 100644 index 0000000..68b37a8 --- /dev/null +++ b/runtime/src/sun/compiler/vm_generator.h @@ -0,0 +1,17 @@ +#ifndef SUN_COMPILER_VM_GENERATOR_H +#define SUN_COMPILER_VM_GENERATOR_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern SVMModule *slcGenerateVMInstructions(SLTNode *moduleNode); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/crc32.h b/runtime/src/sun/tree/crc32.h new file mode 100644 index 0000000..a411a61 --- /dev/null +++ b/runtime/src/sun/tree/crc32.h @@ -0,0 +1,48 @@ +#ifndef SUN_TREE_CRC32_H +#define SUN_TREE_CRC32_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Taken from here: https://web.archive.org/web/20190108202303/http://www.hackersdelight.org/hdcodetxt/crc.c.txt +// Licence: https://web.archive.org/web/20190716204559/http://www.hackersdelight.org/permissions.htm +// See also: https://stackoverflow.com/a/21001712 +// FIXME: Look into https://gist.github.com/badboy/6267743 + +uint32_t crc32c(char *message) { + int i, j; + uint32_t byte, crc, mask; + static uint32_t table[256]; + + /* Set up the table, if necessary. */ + + if (table[1] == 0) { + for (byte = 0; byte <= 255; byte++) { + crc = byte; + for (j = 7; j >= 0; j--) { // Do eight times. + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + table[byte] = crc; + } + } + + /* Through with table setup, now calculate the CRC. */ + + i = 0; + crc = 0xFFFFFFFF; + while ((byte = message[i]) != 0) { + crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF]; + i = i + 1; + } + return ~crc; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/data_type.c b/runtime/src/sun/tree/data_type.c new file mode 100644 index 0000000..f84d524 --- /dev/null +++ b/runtime/src/sun/tree/data_type.c @@ -0,0 +1,24 @@ +#include "data_type.h" + +const char *sltDataTypeToString(SLTDataType dataType) { + switch(dataType) { + default: + case SLTDataTypeUnknown: + return ""; + + case SLTDataTypeNone: + return "None"; + + case SLTDataTypeBoolean: + return "Boolean"; + + case SLTDataTypeInteger: + return "Integer"; + + case SLTDataTypeFloat: + return "Float"; + + case SLTDataTypeString: + return "String"; + } +} diff --git a/runtime/src/sun/tree/data_type.h b/runtime/src/sun/tree/data_type.h new file mode 100644 index 0000000..386f2ac --- /dev/null +++ b/runtime/src/sun/tree/data_type.h @@ -0,0 +1,25 @@ +#ifndef SUN_TREE_DATA_TYPE_H +#define SUN_TREE_DATA_TYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum SLTDataType { + SLTDataTypeUnknown, + + SLTDataTypeNone, + SLTDataTypeBoolean, + SLTDataTypeInteger, + SLTDataTypeFloat, + SLTDataTypeString, +}; +typedef enum SLTDataType SLTDataType; + +extern const char *sltDataTypeToString(SLTDataType dataType); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/node.c b/runtime/src/sun/tree/node.c new file mode 100644 index 0000000..ad91732 --- /dev/null +++ b/runtime/src/sun/tree/node.c @@ -0,0 +1,254 @@ +#include "node_internal.h" + +#include +#include +#include +#include + +const char *sltNodeToString(SLTNode *node) { + return sltNodeTypeToString(node->type); +} + +static SLTNode *node_make_typed(SLTNodeType type, SLTDataType dataType) { + SLTNode *node = (SLTNode *)malloc(sizeof(SLTNode)); + node->type = type; + node->dataType = dataType; + //node->next = NULL; + return node; +} + +static SLTNode *node_make(SLTNodeType type) { + return node_make_typed(type, SLTDataTypeUnknown); +} + +SLTNode *sltNodeMakeIdentifier(const char *name) { + SLTNode *node = node_make(SLTNodeTypeIdentifier); + node->identifierStringValue = strdup(name); // FIXME + node->identifierStringKeyValue = crc32c(name); + return node; +} + +SLTNode *sltNodeMakeBoolean(bool value) { + SLTNode *node = node_make_typed(SLTNodeTypeBoolean, SLTDataTypeBoolean); + node->booleanValue = value; + return node; +} + +SLTNode *sltNodeMakeInteger(int value) { + SLTNode *node = node_make_typed(SLTNodeTypeInteger, SLTDataTypeInteger); + node->integerValue = value; + return node; +} + +SLTNode *sltNodeMakeRawInteger(int value) { + SLTNode *node = node_make_typed(SLTNodeTypeRawInteger, SLTDataTypeInteger); + node->integerValue = value; + return node; +} + +SLTNode *sltNodeMakeFloat(float value) { + SLTNode *node = node_make_typed(SLTNodeTypeFloat, SLTDataTypeFloat); + node->floatValue = value; + return node; +} + +SLTNode *sltNodeMakeString(const char *value) { + SLTNode *node = node_make_typed(SLTNodeTypeString, SLTDataTypeString); + size_t strLen = strlen(value) - 2; // -2 to remove quotes + node->stringValue = malloc(strLen + 1); + strncpy(node->stringValue, value + 1, strLen); + node->stringValue[strLen] = '\0'; + return node; +} + +SLTNode *sltNodeMakeKey(const char *value) { + SLTNode *node = node_make_typed(SLTNodeTypeKey, SLTDataTypeString); + + size_t strLen = strlen(value) - 3; // -3 to remove quotes + unsigned char *key = alloca(strLen + 1); + strncpy(key, value + 2, strLen); + key[strLen] = '\0'; + + node->keyValue = crc32c(key); + + return node; +} + +SLTNode *sltNodeMakeCompound(SLTNode *expression) { + SLTNode *node = node_make(SLTNodeTypeCompound); + node->compoundSubexpression = expression; + return node; +} + +SLTNode *sltNodeMakeArgument(SLTNode *expression) { + SLTNode *node = node_make(SLTNodeTypeArgument); + node->argumentExpression = expression; + return node; +} + +SLTNode *sltNodeMakeArrayAccess(SLTNode *array, SLTNode *access) { + SLTNode *node = node_make(SLTNodeTypeArrayAccess); + node->arrayAccessArray = array; + node->arrayAccessAccess = access; + return node; +} + +SLTNode *sltNodeMakeTypeAccess(SLTNode *type, SLTNode *access) { + SLTNode *node = node_make(SLTNodeTypeTypeAccess); + node->typeAccessType = type; + node->typeAccessAccess = access; + return node; +} + +SLTNode *sltNodeMakeFunctionCall(SLTNode *function, SLTNode *arguments) { + SLTNode *node = node_make(SLTNodeTypeFunctionCall); + node->functionCallFunction = function; + node->functionCallArguments = arguments; + return node; +} + + +SLTNode *sltNodeMakeUnaryOperation(SLTNode *op, SLTNode *operand) { // Can't use "operator" apparently... + SLTNode *node = node_make(SLTNodeTypeUnaryOperation); + node->unaryOperationOperator = op; + node->unaryOperationOperand = operand; + return node; +} + +SLTNode *sltNodeMakeBinaryOperation(SLTNode *op, SLTNode *lhs, SLTNode *rhs) { + SLTNode *node = node_make(SLTNodeTypeBinaryOperation); + node->binaryOperationOperator = op; + node->binaryOperationLHS = lhs; + node->binaryOperationRHS = rhs; + return node; +} + +SLTNode *sltNodeMakeOperator(SLTOperatorType type) { + SLTNode *node = node_make(SLTNodeTypeOperator); + node->operatorType = type; + return node; +} + +SLTNode *sltNodeMakeAssignment(SLTNode *target, SLTNode *source) { + SLTNode *node = node_make(SLTNodeTypeAssignment); + node->assignmentTarget = target; + node->assignmentSource = source; + return node; +} + +SLTNode *sltNodeMakeReturn(SLTNode *expression) { + SLTNode *node = node_make(SLTNodeTypeReturn); + node->returnExpression = expression; + return node; +} + +SLTNode *sltNodeMakeSleep() { + SLTNode *node = node_make(SLTNodeTypeSleep); + return node; +} + +SLTNode *sltNodeMakeBreak() { + SLTNode *node = node_make(SLTNodeTypeBreak); + return node; +} + +SLTNode *sltNodeMakeForIteration(SLTNode *initialExpression, SLTNode *preValidExpression, SLTNode *loopExpression, SLTNode *statement) { + SLTNode *node = node_make(SLTNodeTypeForIteration); + node->iterationInitialExpression = initialExpression; + node->iterationPreValidExpression = preValidExpression; + node->iterationLoopExpression = loopExpression; + node->iterationStatement = statement; + return node; +} + +SLTNode *sltNodeMakeDoIteration(SLTNode *postValidExpression, SLTNode *statement) { + SLTNode *node = node_make(SLTNodeTypeDoIteration); + node->iterationPostValidExpression = postValidExpression; + node->iterationStatement = statement; + return node; +} + +SLTNode *sltNodeMakeWhileIteration(SLTNode *preValidExpression, SLTNode *statement) { + SLTNode *node = node_make(SLTNodeTypeWhileIteration); + node->iterationPreValidExpression = preValidExpression; + node->iterationStatement = statement; + return node; +} + +SLTNode *sltNodeMakeSelection(SLTNode *validExpression, SLTNode *validStatement, SLTNode *invalidStatement) { + SLTNode *node = node_make(SLTNodeTypeSelection); + node->selectionValidExpression = validExpression; + node->selectionValidStatement = validStatement; + node->selectionInvalidStatement = invalidStatement; + return node; +} + +SLTNode *sltNodeMakeStatementBlock(SLTNode *contents) { + SLTNode *node = node_make(SLTNodeTypeStatementBlock); + node->statementBlockContents = contents; + return node; +} + +SLTNode *sltNodeMakeVariableDefinition(SLTNode *type, SLTNode *identifier, SLTNode *defaultExpression) { + SLTNode *node = node_make(SLTNodeTypeVariableDefinition); + node->variableDefinitionType = type; + node->variableDefinitionIdentifier = identifier; + node->variableDefinitionDefaultExpression = defaultExpression; + return node; +} + +SLTNode *sltNodeMakeTypeDefinition(SLTNode *identifier, SLTNode *members) { + SLTNode *node = node_make(SLTNodeTypeTypeDefinition); + node->typeDefinitionIdentifier = identifier; + node->typeDefinitionMembers = members; + return node; +} + +SLTNode *sltNodeMakeTypeMemberDefinition(SLTNode *type, SLTNode *identifier) { + SLTNode *node = node_make(SLTNodeTypeTypeMemberDefinition); + node->typeMemberDefinitionType = type; + node->typeMemberDefinitionIdentifier = identifier; + return node; +} + +SLTNode *sltNodeMakeFunctionDefinition(SLTNode *type, SLTNode *identifier, SLTNode *parameters, SLTNode *body) { + SLTNode *node = node_make(SLTNodeTypeFunctionDefinition); + node->functionDefinitionType = type; + node->functionDefinitionIdentifier = identifier; + node->functionDefinitionParameters = parameters; + node->functionDefinitionBody = body; + return node; +} + +SLTNode *sltNodeMakeFunctionParameterDefinition(SLTNode *type, SLTNode *identifier) { + SLTNode *node = node_make(SLTNodeTypeFunctionParameterDefinition); + node->functionParameterDefinitionType = type; + node->functionParameterDefinitionIdentifier = identifier; + return node; +} + +SLTNode *sltNodeMakeModule(SLTNode *statementsAndDefinitions) { + SLTNode *node = node_make(SLTNodeTypeModule); + node->moduleStatementsAndDefinitions = statementsAndDefinitions; + return node; +} + +SLTNode *sltNodeMakeSequence(SLTNode *head, SLTNode *item) { + assert(head == NULL || head->type == SLTNodeTypeSequence); + + if (item != NULL) { + SLTNode *node = node_make(SLTNodeTypeSequence); + node->sequenceNode = item; + node->sequenceNext = NULL; + + if (head == NULL) { + head = node; + } else { + SLTNode *pos = head; + while (pos->sequenceNext != NULL) pos = pos->sequenceNext; + pos->sequenceNext = node; + } + } + + return head; +} diff --git a/runtime/src/sun/tree/node.h b/runtime/src/sun/tree/node.h new file mode 100644 index 0000000..11e4076 --- /dev/null +++ b/runtime/src/sun/tree/node.h @@ -0,0 +1,68 @@ +#ifndef SUN_TREE_NODE_H +#define SUN_TREE_NODE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SLTNode SLTNode; + +extern const char *sltNodeToString(SLTNode *node); + +extern SLTNode *sltNodeMakeIdentifier(const char *name); + +extern SLTNode *sltNodeMakeBoolean(bool value); +extern SLTNode *sltNodeMakeInteger(int value); +extern SLTNode *sltNodeMakeRawInteger(int value); +extern SLTNode *sltNodeMakeFloat(float value); +extern SLTNode *sltNodeMakeString(const char *value); +extern SLTNode *sltNodeMakeKey(const char *value); + +extern SLTNode *sltNodeMakeCompound(SLTNode *expression); + +extern SLTNode *sltNodeMakeArgument(SLTNode *expression); + +extern SLTNode *sltNodeMakeArrayAccess(SLTNode *array, SLTNode *access); +extern SLTNode *sltNodeMakeTypeAccess(SLTNode *type, SLTNode *access); + +extern SLTNode *sltNodeMakeFunctionCall(SLTNode *function, SLTNode *arguments); + +extern SLTNode *sltNodeMakeUnaryOperation(SLTNode *op, SLTNode *operand); +extern SLTNode *sltNodeMakeBinaryOperation(SLTNode *op, SLTNode *lhs, SLTNode *rhs); + +extern SLTNode *sltNodeMakeOperator(SLTOperatorType type); + +extern SLTNode *sltNodeMakeAssignment(SLTNode *target, SLTNode *source); + +extern SLTNode *sltNodeMakeReturn(SLTNode *expression); +extern SLTNode *sltNodeMakeSleep(void); +extern SLTNode *sltNodeMakeBreak(void); + +extern SLTNode *sltNodeMakeForIteration(SLTNode *initialExpression, SLTNode *preValidExpression, SLTNode *loopExpression, SLTNode *statement); +extern SLTNode *sltNodeMakeDoIteration(SLTNode *postValidExpression, SLTNode *statement); +extern SLTNode *sltNodeMakeWhileIteration(SLTNode *preValidExpression, SLTNode *statement); + +extern SLTNode *sltNodeMakeSelection(SLTNode *validExpression, SLTNode *validStatement, SLTNode *invalidStatement); + +extern SLTNode *sltNodeMakeStatementBlock(SLTNode *contents); + +extern SLTNode *sltNodeMakeVariableDefinition(SLTNode *type, SLTNode *identifier, SLTNode *defaultExpression); + +extern SLTNode *sltNodeMakeTypeDefinition(SLTNode *identifier, SLTNode *members); +extern SLTNode *sltNodeMakeTypeMemberDefinition(SLTNode *type, SLTNode *identifier); + +extern SLTNode *sltNodeMakeFunctionDefinition(SLTNode *type, SLTNode *identifier, SLTNode *parameters, SLTNode *body); +extern SLTNode *sltNodeMakeFunctionParameterDefinition(SLTNode *type, SLTNode *identifier); + +extern SLTNode *sltNodeMakeModule(SLTNode *statementsAndDefinitions); + +extern SLTNode *sltNodeMakeSequence(SLTNode *head, SLTNode *item); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/node_internal.h b/runtime/src/sun/tree/node_internal.h new file mode 100644 index 0000000..687a216 --- /dev/null +++ b/runtime/src/sun/tree/node_internal.h @@ -0,0 +1,154 @@ +#ifndef SUN_TREE_NODE_INTERNAL_H +#define SUN_TREE_NODE_INTERNAL_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct SLTNode { + SLTNodeType type; + SLTDataType dataType; + + union { + struct { + char *identifierStringValue; + unsigned int identifierStringKeyValue; + }; + + struct { + bool booleanValue; + }; + + struct { + int integerValue; + }; + + struct { + float floatValue; + }; + + struct { + char *stringValue; + }; + + struct { + unsigned int keyValue; + }; + + struct { + SLTNode *compoundSubexpression; + }; + + struct { + SLTNode *argumentExpression; + }; + + struct { + SLTNode *arrayAccessArray; + SLTNode *arrayAccessAccess; + }; + + struct { + SLTNode *typeAccessType; + SLTNode *typeAccessAccess; + }; + + struct { + SLTNode *functionCallFunction; + SLTNode *functionCallArguments; + }; + + struct { + SLTNode *unaryOperationOperator; + SLTNode *unaryOperationOperand; + }; + + struct { + SLTNode *binaryOperationOperator; + SLTNode *binaryOperationLHS; + SLTNode *binaryOperationRHS; + }; + + struct { + SLTOperatorType operatorType; + }; + + struct { + SLTNode *assignmentTarget; + SLTNode *assignmentSource; + }; + + struct { + SLTNode *returnExpression; + }; + + struct { + SLTNode *iterationInitialExpression; + SLTNode *iterationPreValidExpression; + SLTNode *iterationPostValidExpression; + SLTNode *iterationLoopExpression; + SLTNode *iterationStatement; + }; + + struct { + SLTNode *selectionValidExpression; + SLTNode *selectionValidStatement; + SLTNode *selectionInvalidStatement; + }; + + struct { + SLTNode *statementBlockContents; + }; + + struct { + SLTNode *variableDefinitionType; + SLTNode *variableDefinitionIdentifier; + SLTNode *variableDefinitionDefaultExpression; + }; + + struct { + SLTNode *typeDefinitionIdentifier; + SLTNode *typeDefinitionMembers; + }; + + struct { + SLTNode *typeMemberDefinitionType; + SLTNode *typeMemberDefinitionIdentifier; + }; + + struct { + SLTNode *functionDefinitionType; + SLTNode *functionDefinitionIdentifier; + SLTNode *functionDefinitionParameters; + SLTNode *functionDefinitionBody; + }; + + struct { + SLTNode *functionParameterDefinitionType; + SLTNode *functionParameterDefinitionIdentifier; + }; + + struct { + SLTNode *moduleStatementsAndDefinitions; + }; + + struct { + SLTNode *sequenceNode; + SLTNode *sequenceNext; + }; + }; + + void *metadata; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/node_type.c b/runtime/src/sun/tree/node_type.c new file mode 100644 index 0000000..1dacf19 --- /dev/null +++ b/runtime/src/sun/tree/node_type.c @@ -0,0 +1,96 @@ +#include "node_type.h" + +const char *sltNodeTypeToString(SLTNodeType nodeType) { + switch(nodeType) { + default: + case SLTNodeTypeUnknown: + return ""; + + case SLTNodeTypeIdentifier: + return "Identifier"; + + case SLTNodeTypeBoolean: + return "Boolean"; + + case SLTNodeTypeInteger: + return "Integer"; + + case SLTNodeTypeRawInteger: + return "Integer (Raw)"; + + case SLTNodeTypeFloat: + return "Float"; + + case SLTNodeTypeString: + return "String"; + + case SLTNodeTypeCompound: + return "Compound"; + + case SLTNodeTypeArgument: + return "Argument"; + + case SLTNodeTypeArrayAccess: + return "ArrayAccess"; + + case SLTNodeTypeTypeAccess: + return "TypeAccess"; + + case SLTNodeTypeFunctionCall: + return "FunctionCall"; + + case SLTNodeTypeUnaryOperation: + return "UnaryOperation"; + + case SLTNodeTypeBinaryOperation: + return "BinaryOperation"; + + case SLTNodeTypeOperator: + return "Operator"; + + case SLTNodeTypeAssignment: + return "Assignment"; + + case SLTNodeTypeReturn: + return "Return"; + + case SLTNodeTypeSleep: + return "Sleep"; + + case SLTNodeTypeBreak: + return "Break"; + + //case SLTNodeTypeIteration: + case SLTNodeTypeForIteration: + case SLTNodeTypeDoIteration: + case SLTNodeTypeWhileIteration: + return "Iteration"; + + case SLTNodeTypeSelection: + return "Selection"; + + case SLTNodeTypeStatementBlock: + return "StatementBlock"; + + case SLTNodeTypeVariableDefinition: + return "VariableDefinition"; + + case SLTNodeTypeTypeDefinition: + return "TypeDefinition"; + + case SLTNodeTypeTypeMemberDefinition: + return "TypeMemberDefinition"; + + case SLTNodeTypeFunctionDefinition: + return "FunctionDefinition"; + + case SLTNodeTypeFunctionParameterDefinition: + return "FunctionParameterDefinition"; + + case SLTNodeTypeModule: + return "Module"; + + case SLTNodeTypeSequence: + return "Sequence"; + } +} diff --git a/runtime/src/sun/tree/node_type.h b/runtime/src/sun/tree/node_type.h new file mode 100644 index 0000000..195d9e6 --- /dev/null +++ b/runtime/src/sun/tree/node_type.h @@ -0,0 +1,69 @@ +#ifndef SUN_TREE_NODE_TYPE_H +#define SUN_TREE_NODE_TYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum SLTNodeType { + SLTNodeTypeUnknown, + + SLTNodeTypeIdentifier, + + SLTNodeTypeBoolean, + SLTNodeTypeInteger, + SLTNodeTypeRawInteger, + SLTNodeTypeFloat, + SLTNodeTypeString, + SLTNodeTypeKey, + + SLTNodeTypeCompound, + + SLTNodeTypeArgument, + + SLTNodeTypeArrayAccess, + SLTNodeTypeTypeAccess, + + SLTNodeTypeFunctionCall, + + SLTNodeTypeUnaryOperation, + SLTNodeTypeBinaryOperation, + + SLTNodeTypeOperator, + + SLTNodeTypeAssignment, + + SLTNodeTypeReturn, + SLTNodeTypeSleep, + SLTNodeTypeBreak, + + SLTNodeTypeForIteration, + SLTNodeTypeDoIteration, + SLTNodeTypeWhileIteration, + + SLTNodeTypeSelection, + + SLTNodeTypeStatementBlock, + + SLTNodeTypeVariableDefinition, + + SLTNodeTypeTypeDefinition, + SLTNodeTypeTypeMemberDefinition, + + SLTNodeTypeFunctionDefinition, + SLTNodeTypeFunctionParameterDefinition, + + SLTNodeTypeModule, + + SLTNodeTypeSequence, // Meta-type, for sequence of other nodes. +}; +typedef enum SLTNodeType SLTNodeType; +static const SLTNodeType kSLTNodeTypeMax = SLTNodeTypeSequence; + +extern const char *sltNodeTypeToString(SLTNodeType nodeType); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/operator_type.c b/runtime/src/sun/tree/operator_type.c new file mode 100644 index 0000000..8195d3a --- /dev/null +++ b/runtime/src/sun/tree/operator_type.c @@ -0,0 +1,81 @@ +#include "operator_type.h" + +const char *sltOperatorTypeToString(SLTOperatorType operatorType) { + switch (operatorType) { + default: + case SLTOperatorTypeUnknown: + return ""; + + case SLTOperatorTypeAdd: + return "Add"; + + case SLTOperatorTypeSubtract: + return "Subtract"; + + case SLTOperatorTypeMultiply: + return "Multiply"; + + case SLTOperatorTypeDivide: + return "Divide"; + + case SLTOperatorTypeModulo: + return "Modulo"; + + case SLTOperatorTypePositive: + return "Positive"; + + case SLTOperatorTypeNegative: + return "Negative"; + + case SLTOperatorTypeBitwiseAnd: + return "BitwiseAnd"; + + case SLTOperatorTypeBitwiseOr: + return "BitwiseOr"; + + case SLTOperatorTypeBitwiseXor: + return "BitwiseXor"; + + case SLTOperatorTypeBitwiseNot: + return "BitwiseNot"; + + case SLTOperatorTypeLogicalAnd: + return "LogicalAnd"; + + case SLTOperatorTypeLogicalOr: + return "LogicalOr"; + + case SLTOperatorTypeLogicalNot: + return "LogicalNot"; + + case SLTOperatorTypeEqual: + return "Equal"; + + case SLTOperatorTypeNotEqual: + return "NotEqual"; + + case SLTOperatorTypeLessThan: + return "LessThan"; + + case SLTOperatorTypeLessThanEqual: + return "LessThanEqual"; + + case SLTOperatorTypeGreaterThan: + return "GreaterThan"; + + case SLTOperatorTypeGreaterThanEqual: + return "GreaterThanEqual"; + + /*case SLTOperatorTypePreIncrement: + return "PreIncrement"; + + case SLTOperatorTypePreDecrement: + return "PreDecrement"; + + case SLTOperatorTypePostIncrement: + return "PostIncrement"; + + case SLTOperatorTypePostDecrement: + return "PostDecrement";*/ + } +} diff --git a/runtime/src/sun/tree/operator_type.h b/runtime/src/sun/tree/operator_type.h new file mode 100644 index 0000000..3a5569e --- /dev/null +++ b/runtime/src/sun/tree/operator_type.h @@ -0,0 +1,49 @@ +#ifndef SUN_TREE_OPERATOR_TYPE_H +#define SUN_TREE_OPERATOR_TYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum SLTOperatorType { + SLTOperatorTypeUnknown, + + SLTOperatorTypeAdd, + SLTOperatorTypeSubtract, + SLTOperatorTypeMultiply, + SLTOperatorTypeDivide, + SLTOperatorTypeModulo, + + SLTOperatorTypePositive, + SLTOperatorTypeNegative, + + SLTOperatorTypeBitwiseAnd, + SLTOperatorTypeBitwiseOr, + SLTOperatorTypeBitwiseXor, + SLTOperatorTypeBitwiseNot, + + SLTOperatorTypeLogicalAnd, + SLTOperatorTypeLogicalOr, + SLTOperatorTypeLogicalNot, + + SLTOperatorTypeEqual, + SLTOperatorTypeNotEqual, + SLTOperatorTypeLessThan, + SLTOperatorTypeLessThanEqual, + SLTOperatorTypeGreaterThan, + SLTOperatorTypeGreaterThanEqual, + + //SLTOperatorTypePreIncrement, + //SLTOperatorTypePreDecrement, + //SLTOperatorTypePostIncrement, + //SLTOperatorTypePostDecrement, +}; +typedef enum SLTOperatorType SLTOperatorType; + +extern const char *sltOperatorTypeToString(SLTOperatorType operatorType); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/tree/tree.c b/runtime/src/sun/tree/tree.c new file mode 100644 index 0000000..118f9c6 --- /dev/null +++ b/runtime/src/sun/tree/tree.c @@ -0,0 +1,185 @@ +#include "tree.h" + +#include "node_internal.h" +#include "node_type.h" + +#include + +typedef struct { + SLTTreeIteratorCallback callback; + SLTTreeIteratorCallback postCallback; + void *userParameter; +} TreeIteratorCallbackDetails; + +static SLTNode *treeIterateCallback(SLTNode *node, void *extra); +static SLTNode *treeIteratePostCallback(SLTNode *node, void *extra); + +void sltTreeIterate(SLTNode *root, SLTTreeIteratorCallback callback, SLTTreeIteratorCallback postCallback, void *userParameter) { + TreeIteratorCallbackDetails details = { + .callback = callback, + .postCallback = postCallback, + .userParameter = userParameter, + }; + sltTreeMap(root, (callback != NULL) ? treeIterateCallback : NULL, (postCallback != NULL) ? treeIteratePostCallback : NULL, &details); +} + +SLTNode *sltTreeMap(SLTNode *root, SLTTreeMapCallback callback, SLTTreeMapCallback postCallback, void *userParameter){ + SLTNode *n = root; + + if (callback != NULL && n != NULL && n->type != SLTNodeTypeSequence) { + n = callback(n, userParameter); + } + + if (n != NULL) { + switch (n->type) { + default: + case SLTNodeTypeUnknown: + /* Produce error? */ + break; + + /* These have no child nodes */ + case SLTNodeTypeIdentifier: + case SLTNodeTypeInteger: + case SLTNodeTypeFloat: + case SLTNodeTypeString: + case SLTNodeTypeOperator: + break; + + case SLTNodeTypeCompound: + n->compoundSubexpression = sltTreeMap(n->compoundSubexpression, callback, postCallback, userParameter); + break; + + case SLTNodeTypeArgument: + n->argumentExpression = sltTreeMap(n->argumentExpression, callback, postCallback, userParameter); + break; + + case SLTNodeTypeArrayAccess: + n->arrayAccessArray = sltTreeMap(n->arrayAccessArray, callback, postCallback, userParameter); + n->arrayAccessAccess = sltTreeMap(n->arrayAccessAccess, callback, postCallback, userParameter); + break; + + case SLTNodeTypeTypeAccess: + n->typeAccessType = sltTreeMap(n->typeAccessType, callback, postCallback, userParameter); + n->typeAccessAccess = sltTreeMap(n->typeAccessAccess, callback, postCallback, userParameter); + break; + + case SLTNodeTypeFunctionCall: + n->functionCallFunction = sltTreeMap(n->functionCallFunction, callback, postCallback, userParameter); + n->functionCallArguments = sltTreeMap(n->functionCallArguments, callback, postCallback, userParameter); + break; + + case SLTNodeTypeUnaryOperation: + n->unaryOperationOperator = sltTreeMap(n->unaryOperationOperator, callback, postCallback, userParameter); + n->unaryOperationOperand = sltTreeMap(n->unaryOperationOperand, callback, postCallback, userParameter); + break; + + case SLTNodeTypeBinaryOperation: + n->binaryOperationOperator = sltTreeMap(n->binaryOperationOperator, callback, postCallback, userParameter); + n->binaryOperationLHS = sltTreeMap(n->binaryOperationLHS, callback, postCallback, userParameter); + n->binaryOperationRHS = sltTreeMap(n->binaryOperationRHS, callback, postCallback, userParameter); + break; + + case SLTNodeTypeAssignment: + n->assignmentTarget = sltTreeMap(n->assignmentTarget, callback, postCallback, userParameter); + n->assignmentSource = sltTreeMap(n->assignmentSource, callback, postCallback, userParameter); + break; + + case SLTNodeTypeReturn: + n->returnExpression = sltTreeMap(n->returnExpression, callback, postCallback, userParameter); + break; + + //case SLTNodeTypeIteration: + case SLTNodeTypeForIteration: + case SLTNodeTypeDoIteration: + case SLTNodeTypeWhileIteration: + n->iterationInitialExpression = sltTreeMap(n->iterationInitialExpression, callback, postCallback, userParameter); + n->iterationPreValidExpression = sltTreeMap(n->iterationPreValidExpression, callback, postCallback, userParameter); + n->iterationPostValidExpression = sltTreeMap(n->iterationPostValidExpression, callback, postCallback, userParameter); + n->iterationLoopExpression = sltTreeMap(n->iterationLoopExpression, callback, postCallback, userParameter); + n->iterationStatement = sltTreeMap(n->iterationStatement, callback, postCallback, userParameter); + break; + + case SLTNodeTypeSelection: + n->selectionValidExpression = sltTreeMap(n->selectionValidExpression, callback, postCallback, userParameter); + n->selectionValidStatement = sltTreeMap(n->selectionValidStatement, callback, postCallback, userParameter); + n->selectionInvalidStatement = sltTreeMap(n->selectionInvalidStatement, callback, postCallback, userParameter); + break; + + case SLTNodeTypeStatementBlock: + n->statementBlockContents = sltTreeMap(n->statementBlockContents, callback, postCallback, userParameter); + break; + + case SLTNodeTypeVariableDefinition: + n->variableDefinitionType = sltTreeMap(n->variableDefinitionType, callback, postCallback, userParameter); + n->variableDefinitionIdentifier = sltTreeMap(n->variableDefinitionIdentifier, callback, postCallback, userParameter); + n->variableDefinitionDefaultExpression = sltTreeMap(n->variableDefinitionDefaultExpression, callback, postCallback, userParameter); + break; + + case SLTNodeTypeTypeDefinition: + n->typeDefinitionIdentifier = sltTreeMap(n->typeDefinitionIdentifier, callback, postCallback, userParameter); + n->typeDefinitionMembers = sltTreeMap(n->typeDefinitionMembers, callback, postCallback, userParameter); + break; + + case SLTNodeTypeTypeMemberDefinition: + n->typeMemberDefinitionType = sltTreeMap(n->typeMemberDefinitionType, callback, postCallback, userParameter); + n->typeMemberDefinitionIdentifier = sltTreeMap(n->typeMemberDefinitionIdentifier, callback, postCallback, userParameter); + break; + + case SLTNodeTypeFunctionDefinition: + n->functionDefinitionType = sltTreeMap(n->functionDefinitionType, callback, postCallback, userParameter); + n->functionDefinitionIdentifier = sltTreeMap(n->functionDefinitionIdentifier, callback, postCallback, userParameter); + n->functionDefinitionParameters = sltTreeMap(n->functionDefinitionParameters, callback, postCallback, userParameter); + n->functionDefinitionBody = sltTreeMap(n->functionDefinitionBody, callback, postCallback, userParameter); + break; + + case SLTNodeTypeFunctionParameterDefinition: + n->functionParameterDefinitionType = sltTreeMap(n->functionParameterDefinitionType, callback, postCallback, userParameter); + n->functionParameterDefinitionIdentifier = sltTreeMap(n->functionParameterDefinitionIdentifier, callback, postCallback, userParameter); + break; + + case SLTNodeTypeModule: + n->moduleStatementsAndDefinitions = sltTreeMap(n->moduleStatementsAndDefinitions, callback, postCallback, userParameter); + break; + + case SLTNodeTypeSequence: { + SLTNode *readHead = n; + SLTNode *writeHead = n; + SLTNode **writeLast = &n; + + *writeLast = NULL; + + while (readHead != NULL) { + writeHead->sequenceNode = sltTreeMap(readHead->sequenceNode, callback, postCallback, userParameter); + readHead = readHead->sequenceNext; + + if (writeHead->sequenceNode != NULL) { + *writeLast = writeHead; + writeLast = &writeHead->sequenceNext; + writeHead = writeHead->sequenceNext; + *writeLast = NULL; + } + } + + break; + } + } + } + + if (postCallback != NULL && n != NULL && n->type != SLTNodeTypeSequence) { + n = postCallback(n, userParameter); + } + + return n; +} + +SLTNode *treeIterateCallback(SLTNode *node, void *extra) { + TreeIteratorCallbackDetails *details = (TreeIteratorCallbackDetails *)extra; + details->callback(node, details->userParameter); + return node; +} + +SLTNode *treeIteratePostCallback(SLTNode *node, void *extra) { + TreeIteratorCallbackDetails *details = (TreeIteratorCallbackDetails *)extra; + details->postCallback(node, details->userParameter); + return node; +} diff --git a/runtime/src/sun/tree/tree.h b/runtime/src/sun/tree/tree.h new file mode 100644 index 0000000..366e2ad --- /dev/null +++ b/runtime/src/sun/tree/tree.h @@ -0,0 +1,20 @@ +#ifndef SUN_TREE_TREE_H +#define SUN_TREE_TREE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*SLTTreeIteratorCallback)(SLTNode *node, void *userParameter); +typedef SLTNode *(*SLTTreeMapCallback)(SLTNode *node, void *userParameter); + +extern void sltTreeIterate(SLTNode *root, SLTTreeIteratorCallback callback, SLTTreeIteratorCallback postCallback, void *userParameter); +extern SLTNode *sltTreeMap(SLTNode *root, SLTTreeMapCallback callback, SLTTreeMapCallback postCallback, void *userParameter); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/vm/fixed.c b/runtime/src/sun/vm/fixed.c new file mode 100644 index 0000000..dba6b4d --- /dev/null +++ b/runtime/src/sun/vm/fixed.c @@ -0,0 +1,73 @@ +#include "fixed.h" + +#include + +Fixed fixedSqrt(Fixed value) { + float f = FIXED_TO_FLOAT(value); + float f2 = sqrtf(f); + return FIXED_FROM_FLOAT(f2); + + +#if 0 + Fixed root; + + register unsigned long remHi, remLo, testDiv, count; + + root.raw = 0;/* Clear root */ + remHi = 0;/* Clear high part of partial remainder */ + remLo = value.raw;/* Get argument into low part of partial remainder */ + count = FIXED_FRACTIONAL_BITS;/* Load loop counter */ + + do { + remHi = (remHi << FIXED_INTEGRAL_BITS) | (remLo >> FIXED_FRACTIONAL_BITS); + remLo <<= 2; /* get 2 bits of arg */ + root.raw <<= 1; /* Get ready for the next bit in the root */ + testDiv = (root.raw << 1) + 1;/* Test radical */ + + if (remHi >= testDiv) { + remHi -= testDiv; + root.raw++; + } + } while (count-- != 0); + + return(root); +#endif +} + +Fixed fixedSin(Fixed value) { + float f = FIXED_TO_FLOAT(value); + float f2 = sinf(f * M_PI * 2.0f); + return FIXED_FROM_FLOAT(f2); +} + +Fixed fixedCos(Fixed value) { + float f = FIXED_TO_FLOAT(value); + float f2 = cosf(f * M_PI * 2.0f); + return FIXED_FROM_FLOAT(f2); +} + +Fixed fixedAtan2(Fixed x, Fixed y) { + float f1 = FIXED_TO_FLOAT(y); // Notice swap + float f2 = FIXED_TO_FLOAT(x); + float f3 = atan2f(f1, f2); + float f4 = f3 / (M_PI * 2.0f); + return FIXED_FROM_FLOAT(f4); +} + +Fixed fixedAbs(Fixed value) { + float f = FIXED_TO_FLOAT(value); + float f2 = fabsf(f); + return FIXED_FROM_FLOAT(f2); +} + +Fixed fixedCeil(Fixed value) { + float f = FIXED_TO_FLOAT(value); + float f2 = ceilf(f); + return FIXED_FROM_FLOAT(f2); +} + +Fixed fixedFloor(Fixed value) { + float f = FIXED_TO_FLOAT(value); + float f2 = floorf(f); + return FIXED_FROM_FLOAT(f2); +} diff --git a/runtime/src/sun/vm/fixed.h b/runtime/src/sun/vm/fixed.h new file mode 100644 index 0000000..db36671 --- /dev/null +++ b/runtime/src/sun/vm/fixed.h @@ -0,0 +1,96 @@ +#ifndef SUN_VM_FIXED_H +#define SUN_VM_FIXED_H + +// Reference: https://en.wikipedia.org/wiki/Q_(number_format) +// http://www.superkits.net/whitepapers/Fixed%20Point%20Representation%20&%20Fractional%20Math.pdf + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define FIXED_FRACTIONAL_BITS 8 +#define FIXED_INTEGRAL_BITS 8 + +#define FIXED_ONE (1 << FIXED_FRACTIONAL_BITS) + +typedef int32_t Fixed; +static_assert(sizeof(Fixed) == sizeof(int32_t), "Fixed incorrect size"); + +#define _fixed(v) ((Fixed)((v))) + +#define FIXED(x) (_fixed((x) * FIXED_ONE)) +#define FIXED_TO_INT(x) ((int)((int32_t)(x) / FIXED_ONE)) + +#define FIXED_FROM_FLOAT(x) (_fixed((x) * (float)FIXED_ONE)) +#define FIXED_TO_FLOAT(x) ((float)((x) / (float)FIXED_ONE)) + +#define fixedLT(lhs, rhs) ((int32_t)(lhs) < (int32_t)(rhs)) +#define fixedGT(lhs, rhs) ((int32_t)(lhs) > (int32_t)(rhs)) + +#define fixedNegate(v) (_fixed(-(int32_t)(v))) + +#define fixedAdd(lhs, rhs) (_fixed((int32_t)(lhs) + (int32_t)(rhs))) +#define fixedSubtract(lhs, rhs) (_fixed((int32_t)(lhs) - (int32_t)(rhs))) + +#define fixedMultiply(lhs, rhs) (_fixed((((int32_t)(lhs) * (int32_t)(rhs))) / FIXED_ONE)) +#define fixedDivide(lhs, rhs) (_fixed(((int32_t)(lhs * FIXED_ONE) / (int32_t)(rhs)))) +#define fixedMod(lhs, rhs) (_fixed((int32_t)(lhs) % (int32_t)(rhs))) + +static inline Fixed fixedSgn(Fixed v) { + return v == 0 ? 0 : (fixedGT(v, 0) ? FIXED(1) : FIXED(-1)); +} + +static inline Fixed fixedMin(Fixed lhs, Fixed rhs) { + return fixedLT(lhs, rhs) ? lhs : rhs; +} + +static inline Fixed fixedMax(Fixed lhs, Fixed rhs) { + return fixedGT(lhs, rhs) ? lhs : rhs; +} + +static inline Fixed fixedMid(Fixed val1, Fixed val2, Fixed val3) { + return fixedMin(fixedMin(fixedMax(val1, val2), fixedMax(val2, val3)), fixedMax(val1, val3)); +} + +static inline Fixed fixedClamp(Fixed a, Fixed b, Fixed v) { + return fixedMin(fixedMax(v, a), b); +} + +static inline Fixed fixedUnclampedLerp(Fixed a, Fixed b, Fixed t) { + Fixed v = fixedSubtract(fixedMultiply(a, fixedSubtract(FIXED(1), t)), fixedMultiply(b, t)); + return v; +} + +static inline Fixed fixedUnclampedUnlerp(Fixed a, Fixed b, Fixed v) { + Fixed t = fixedDivide(fixedSubtract(v, a), fixedSubtract(b, a)); + return t; +} + +static inline Fixed fixedLerp(Fixed a, Fixed b, Fixed t) { + Fixed clampedT = fixedClamp(FIXED(0), FIXED(1), t); + Fixed v = fixedUnclampedLerp(a, b, clampedT); + return v; +} + +static inline Fixed fixedUnlerp(Fixed a, Fixed b, Fixed v) { + Fixed t = fixedUnclampedUnlerp(a, b, v); + Fixed clampedT = fixedClamp(FIXED(0), FIXED(1), t); + return clampedT; +} + +extern Fixed fixedSqrt(Fixed value); +extern Fixed fixedSin(Fixed value); +extern Fixed fixedCos(Fixed value); +extern Fixed fixedAtan2(Fixed x, Fixed y); +extern Fixed fixedAbs(Fixed value); +extern Fixed fixedCeil(Fixed value); +extern Fixed fixedFloor(Fixed value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/vm/instruction.c b/runtime/src/sun/vm/instruction.c new file mode 100644 index 0000000..408d07b --- /dev/null +++ b/runtime/src/sun/vm/instruction.c @@ -0,0 +1,98 @@ +#include + +#include + +static_assert(sizeof(SVMInstruction) == sizeof(SVMOpcode) + sizeof(SVMOperand) * 3, "invalid size"); +static_assert(sizeof(SVMOperand) == sizeof(uint32_t), "raw will not work..."); + +const char *svmOpcodeToString(SVMOpcode opcode) { + switch(opcode) { + default: + case SVMOpcodeInvalid: + return ""; + + case SVMOpcodeMOV: + return "MOV"; + + case SVMOpcodeSET: + return "SET"; + + case SVMOpcodeINV: + return "INV"; + + case SVMOpcodeBNOT: + return "BNOT"; + + case SVMOpcodeNOT: + return "NOT"; + + case SVMOpcodeADD: + return "ADD"; + + case SVMOpcodeSUB: + return "SUB"; + + case SVMOpcodeMUL: + return "MUL"; + + case SVMOpcodeDIV: + return "DIV"; + + case SVMOpcodeMOD: + return "MOD"; + + case SVMOpcodeBAND: + return "BAND"; + + case SVMOpcodeBOR: + return "BOR"; + + case SVMOpcodeBXOR: + return "BXOR"; + + case SVMOpcodeAND: + return "AND"; + + case SVMOpcodeOR: + return "OR"; + + case SVMOpcodeEQ: + return "EQ"; + + case SVMOpcodeNEQ: + return "NEQ"; + + case SVMOpcodeLT: + return "LT"; + + case SVMOpcodeLTEQ: + return "LTEQ"; + + case SVMOpcodeGT: + return "GT"; + + case SVMOpcodeGTEQ: + return "GTEQ"; + + case SVMOpcodeSLEEP: + return "SLEEP"; + + case SVMOpcodeSTK: + return "STK"; + + case SVMOpcodePOPJUMP: + return "POPJUMP"; + + case SVMOpcodeJUMP: + return "JUMP"; + + case SVMOpcodePUSHJUMP: + return "PUSHJUMP"; + + case SVMOpcodeCALL: + return "CALL"; + + case SVMOpcodeJT: + return "JT"; + } +} diff --git a/runtime/src/sun/vm/instruction.h b/runtime/src/sun/vm/instruction.h new file mode 100644 index 0000000..4ecefd7 --- /dev/null +++ b/runtime/src/sun/vm/instruction.h @@ -0,0 +1,85 @@ +#ifndef SUN_VM_INSTRUCTION_H +#define SUN_VM_INSTRUCTION_H + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum SVMOpcode { + SVMOpcodeInvalid, + + SVMOpcodeMOV, + SVMOpcodeSET, + + SVMOpcodeINV, + SVMOpcodeBNOT, + SVMOpcodeNOT, + SVMOpcodeADD, + SVMOpcodeSUB, + SVMOpcodeMUL, + SVMOpcodeDIV, + SVMOpcodeMOD, + SVMOpcodeBAND, + SVMOpcodeBOR, + SVMOpcodeBXOR, + SVMOpcodeAND, + SVMOpcodeOR, + SVMOpcodeEQ, + SVMOpcodeNEQ, + SVMOpcodeLT, + SVMOpcodeLTEQ, + SVMOpcodeGT, + SVMOpcodeGTEQ, + + SVMOpcodeSTK, + + SVMOpcodeSLEEP, + SVMOpcodePOPJUMP, + SVMOpcodeJUMP, + SVMOpcodePUSHJUMP, + SVMOpcodeCALL, + + SVMOpcodeJT, +}; +typedef enum SVMOpcode SVMOpcode; + +extern const char *svmOpcodeToString(SVMOpcode opcode); + +typedef int32_t SVMStackOffset; +typedef Fixed/*float*/ SVMFloat; +typedef Fixed/*int32_t*/ SVMInteger; +typedef uint32_t SVMPointer; + +union SVMOperand { + SVMStackOffset stackOffset; + SVMFloat floatLiteral; + SVMInteger integerLiteral; + SVMPointer pointerLiteral; // Strings, function pointer + int32_t __raw; +}; +typedef union SVMOperand SVMOperand; + +struct SVMInstruction { + SVMOpcode opcode; + union __attribute__((__packed__)) { + struct __attribute__((__packed__)) { + SVMOperand dst; + SVMOperand p1; + SVMOperand p2; + }; + + SVMOperand operands[3]; + }; +}; +typedef struct SVMInstruction SVMInstruction; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/vm/vm.c b/runtime/src/sun/vm/vm.c new file mode 100644 index 0000000..1d80218 --- /dev/null +++ b/runtime/src/sun/vm/vm.c @@ -0,0 +1,335 @@ +#include "vm_internal.h" + +#include // memcpy +#include // printf, fixme, remove +#include // fmodf, fixme, remove + +//struct SVMVM { +//// SVMVMConfiguration configuration; +//}; + +#define SVMVMMaxStack 128 +#define SVMVMMaxPCStack 32 + +struct SVMModuleInstance { + //SVMVM *vm; + SVMFunctionLookupCallback lookupCallback; + SVMModule *module; + void *userParam; + + char *strings; + SVMInstruction *instructions; + + uint32_t currentStackIdx; + SVMOperand stack[SVMVMMaxStack]; + + uint32_t currentPCStackIdx; + SVMPointer pcStack[SVMVMMaxPCStack]; +}; + +//SVMVM *svmCreateVM(const SVMVMConfiguration *configuration) { +// SVMVM *vm = configuration->malloc(sizeof(SVMVM)); +// memcpy(&vm->configuration, configuration, sizeof(SVMVMConfiguration)); +// return vm; +//} + + +//SVMModuleInstance *svmCreateModuleInstance(SVMVM *vm, SVMModule *module, void *userParam) { +// SVMModuleInstance *instance = vm->configuration.malloc(sizeof(SVMModuleInstance)); +// instance->vm = vm; +// instance->module = module; +// instance->userParam = userParam; +// instance->strings = (char *)((void *)module + sizeof(SVMModule)); +// instance->instructions = (SVMInstruction *)((void *)module + sizeof(SVMModule) + module->stringBlobLength); +// instance->currentStackIdx = 0; +// instance->currentPCStackIdx = 0; +// instance->pcStack[0] = 0; +// return instance; +//} + + +size_t svmGetModuleInstanceSize(SVMModule *module) { + return sizeof(SVMModuleInstance); +} + +SVMModuleInstance *svnResetModuleInstanceMemory(SVMModule *module, void *memory, void *userParameter, SVMFunctionLookupCallback lookupCallback) { + SVMModuleInstance *instance = (SVMModuleInstance *)memory; + instance->lookupCallback = lookupCallback; + instance->module = module; + instance->userParam = userParameter; + instance->strings = (char *)((void *)module + sizeof(SVMModule)); + instance->instructions = (SVMInstruction *)((void *)module + sizeof(SVMModule) + module->stringBlobLength); + instance->currentStackIdx = 0; + instance->currentPCStackIdx = 0; + instance->pcStack[0] = 0; + return instance; +} + +void *svmGetModuleInstanceUserParameter(SVMModuleInstance *instance) { + return instance->userParam; +} + +SVMRunOutcome svmRunModuleInstance(SVMModuleInstance *instance) { + #define resolveStack(v) ((v) >= 0 ? (instance->currentStackIdx + (v)) : (SVMVMMaxStack + (v))) + + for (;;) { + if(instance->currentPCStackIdx < 0 || instance->currentPCStackIdx >= SVMVMMaxPCStack) { + printf("EXCEEDED PCSTACK\n"); + return SVMRunOutcomeError; + } + + SVMPointer *instructionIdxP = &instance->pcStack[instance->currentPCStackIdx]; + SVMPointer instructionIdx = *instructionIdxP; + + if (instructionIdx >= instance->module->numInstructions) return SVMRunOutcomeFinished; + + // ... + SVMInstruction instruction = instance->instructions[instructionIdx]; + + switch (instruction.opcode) { + case SVMOpcodeInvalid: + default: + printf("ERROR, FOUND BAD OPCODE: %u %u\n", instruction.opcode, instructionIdx); + __builtin_unreachable(); + //exit(1); + return SVMRunOutcomeError; + + case SVMOpcodeMOV: { + int32_t raw = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = raw; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeSET: { + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = instruction.p1.__raw; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + // FIXME: Use of float + case SVMOpcodeINV: { + SVMFloat raw = instance->stack[resolveStack(instruction.p1.stackOffset)].floatLiteral; + instance->stack[resolveStack(instruction.dst.stackOffset)].floatLiteral = fixedNegate(raw); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeBNOT: { + int32_t raw = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = ~(raw); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeNOT: { + int32_t raw = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = !(raw); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + // FIXME: Use of float + case SVMOpcodeADD: { + SVMFloat rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].floatLiteral; + SVMFloat rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].floatLiteral; + instance->stack[resolveStack(instruction.dst.stackOffset)].floatLiteral = fixedAdd(rawLHS, rawRHS); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + // FIXME: Use of float + case SVMOpcodeSUB: { + SVMFloat rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].floatLiteral; + SVMFloat rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].floatLiteral; + instance->stack[resolveStack(instruction.dst.stackOffset)].floatLiteral = fixedSubtract(rawLHS, rawRHS); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + // FIXME: Use of float + case SVMOpcodeMUL: { + SVMFloat rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].floatLiteral; + SVMFloat rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].floatLiteral; + instance->stack[resolveStack(instruction.dst.stackOffset)].floatLiteral = fixedMultiply(rawLHS, rawRHS); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + // FIXME: Use of float + case SVMOpcodeDIV: { + SVMFloat rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].floatLiteral; + SVMFloat rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].floatLiteral; + instance->stack[resolveStack(instruction.dst.stackOffset)].floatLiteral = fixedDivide(rawLHS, rawRHS); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + // FIXME: Use of float + case SVMOpcodeMOD: { + SVMFloat rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].floatLiteral; + SVMFloat rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].floatLiteral; + instance->stack[resolveStack(instruction.dst.stackOffset)].floatLiteral = fixedMod(rawLHS, rawRHS); + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeBAND: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS & rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeBOR: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS | rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeBXOR: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS ^ rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeAND: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS && rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeOR: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS || rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeEQ: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS == rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeNEQ: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS != rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeLT: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS < rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeLTEQ: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS <= rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeGT: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS > rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeGTEQ: { + int32_t rawLHS = instance->stack[resolveStack(instruction.p1.stackOffset)].__raw; + int32_t rawRHS = instance->stack[resolveStack(instruction.p2.stackOffset)].__raw; + instance->stack[resolveStack(instruction.dst.stackOffset)].__raw = rawLHS >= rawRHS; + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeSTK: { + SVMStackOffset offset = instruction.dst.stackOffset; + instance->currentStackIdx += offset; + if(instance->currentStackIdx < 0 || instance->currentStackIdx >= SVMVMMaxStack) { + printf("EXCEEDED STACK\n"); + return SVMRunOutcomeError; + } + // assert >=0 ? + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeSLEEP: { + *instructionIdxP = *instructionIdxP + 1; + return SVMRunOutcomeSuspended; + } + + case SVMOpcodePOPJUMP: { + instance->currentPCStackIdx--; + // assert >=0 ? + break; + } + + case SVMOpcodeJUMP: { + *instructionIdxP = instruction.dst.pointerLiteral; + break; + } + + case SVMOpcodePUSHJUMP: { + *instructionIdxP = *instructionIdxP + 1; + instance->currentPCStackIdx++; + instance->pcStack[instance->currentPCStackIdx] = instruction.dst.pointerLiteral; + break; + } + + case SVMOpcodeCALL: { +// const char *name = svmGetString(instance, instruction.dst.pointerLiteral); + SVMFunctionCallback function = instance->lookupCallback(instruction.dst.pointerLiteral, instance->userParam); + if (function != NULL) { + int32_t parameterCount = (int32_t)instruction.p1.integerLiteral; + function(instance, parameterCount, &instance->stack[instance->currentStackIdx]); // FIXME + } + *instructionIdxP = *instructionIdxP + 1; + break; + } + + case SVMOpcodeJT: { + int32_t value = instance->stack[resolveStack(instruction.dst.stackOffset)].__raw; + if (value) { + *instructionIdxP = instruction.p1.pointerLiteral; + } else { + *instructionIdxP = *instructionIdxP + 1; + } + + break; + } + } + } +} + +const char *svmGetString(SVMModuleInstance *instance, int32_t ptr) { + return &instance->strings[ptr]; +} + +SVMPublic *svmGetPublicReference(SVMModule *instance, const char *nameFmt, ...) { + +} + +SVMOperand svmGetPublicValue(SVMModuleInstance *instance, int32_t ptr) { + +} diff --git a/runtime/src/sun/vm/vm.h b/runtime/src/sun/vm/vm.h new file mode 100644 index 0000000..ae6c9fb --- /dev/null +++ b/runtime/src/sun/vm/vm.h @@ -0,0 +1,64 @@ +#ifndef SUN_VM_VM_H +#define SUN_VM_VM_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SVMVM SVMVM; + +typedef struct SVMModule SVMModule; +typedef struct SVMModuleInstance SVMModuleInstance; + +typedef struct SVMModuleInstance SVMModuleInstance; + +typedef struct SVMPublic SVMPublic; + +typedef void *(*SVMCMallocCallback)(size_t size, void *userParameter); +typedef void (*SVMFreeCallback)(void *memory, void *userParameter); + +typedef void (*SVMFunctionCallback)(SVMModuleInstance *instance, int32_t parameterCount, SVMOperand stack[]); +typedef SVMFunctionCallback (*SVMFunctionLookupCallback)(uint32_t nameCRC, void *userParameter); + +typedef void (*SVMErrorCallback)(SVMModuleInstance *instance, const char *errorString, void *userParameter); + +//struct SVMVMConfiguration { +// SVMCMallocCallback malloc; +// SVMFreeCallback free; +// SVMCallFunctionCallback lookup; +// void *lookupUserParam; +//}; +//typedef struct SVMVMConfiguration SVMVMConfiguration; + +enum SVMRunOutcome { + SVMRunOutcomeError, + SVMRunOutcomeSuspended, + SVMRunOutcomeFinished, +}; +typedef enum SVMRunOutcome SVMRunOutcome; + +//extern SVMVM *svmCreateVM(const SVMVMConfiguration *configuration); + +//extern SVMModuleInstance *svmCreateModuleInstance(SVMVM *vm, SVMModule *module, void *userParam); // fixme, add stack memory?? + +extern size_t svmGetModuleInstanceSize(SVMModule *module); + +extern SVMModuleInstance *svnResetModuleInstanceMemory(SVMModule *module, void *memory, void *userParameter, SVMFunctionLookupCallback lookupCallback); +extern void *svmGetModuleInstanceUserParameter(SVMModuleInstance *instance); + +extern SVMRunOutcome svmRunModuleInstance(SVMModuleInstance *instance); + +extern const char *svmGetString(SVMModuleInstance *instance, int32_t ptr); + +extern SVMPublic *svmGetPublicReference(SVMModule *instance, const char *nameFmt, ...); +extern SVMOperand svmGetPublicValue(SVMModuleInstance *instance, int32_t ptr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/runtime/src/sun/vm/vm_internal.h b/runtime/src/sun/vm/vm_internal.h new file mode 100644 index 0000000..73e7b4b --- /dev/null +++ b/runtime/src/sun/vm/vm_internal.h @@ -0,0 +1,30 @@ +#ifndef SUN_VM_VM_INTERNAL_H +#define SUN_VM_VM_INTERNAL_H + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct SVMModule { + char header[4]; + uint32_t magic; + uint32_t stringBlobLength; + uint32_t numFunctions; + uint32_t numInstructions; +}; + +struct SVMModuleFunctionDetails { + SVMPointer nameStringPtr; + SVMPointer functionInstruction; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..7730e86 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.10) + +project(suntest C) + +set(SUNCC ${PROJECT_BINARY_DIR}/../compiler/suncc) +function(target_add_sun_sources TARGET) + foreach(SRC ${ARGN}) + cmake_path(GET SRC STEM SUN_BASENAME) + set(SUN_OUTPUT ${PROJECT_BINARY_DIR}/${SUN_BASENAME}.c) + + add_custom_command( + OUTPUT ${SUN_OUTPUT} + DEPENDS ${SRC} + COMMAND ${SUNCC} ${SUN_OUTPUT} ${SRC} + ) + + list(APPEND SUN_C_SOURCES ${SUN_OUTPUT}) + endforeach() + + target_sources(${TARGET} PRIVATE ${SUN_C_SOURCES}) +endfunction() + +set(SUN_TEST_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/test_1.sun +) + +add_executable(suntest main.c) +target_add_sun_sources(suntest ${SUN_TEST_SOURCES}) +#target_include_directories(suncc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +#target_link_libraries(suncc suncore) +#target_link_libraries(suncc ${FLEX_LIBRARIES}) diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_1.sun b/tests/test_1.sun new file mode 100644 index 0000000..4c7b8f2 --- /dev/null +++ b/tests/test_1.sun @@ -0,0 +1,69 @@ +struct basic_type { + //string a; + int b; +} + +int a; +int b; + +while (true) { + print(); + sleep; +} + +/* OperatorTypeNegative + +sdlfkjlaskdfadsf + + + +void main(int a, int b, int c) { + int a = 10; + //string fish = "hekkopo"; + print();;;;;; + + if (a) { + fish(this, out); + set(); + } + +int i; + for (i = 20; i <= 20; ++i) { + this(); + + sleep; + } + +int z; + while (z>10) { + fish(); + } + +int x; + do { + egg(); + } while (x < 100); + + + a = a + 1; + a = a - 1; + a = a * 1; + a = a / 1; + + a+=1; + a-=1; + a*=1; + a/=1; + + a = a && a; + a = a || a; + a = !a; + + a = a & a; + a = a | a; + a = ~a; + + +} + +*/ \ No newline at end of file