--- /dev/null
+cmake_minimum_required(VERSION 3.10)
+
+project(sun C)
+
+add_subdirectory(core)
+add_subdirectory(compiler)
+add_subdirectory(vm)
+
+#add_subdirectory(tests)
--- /dev/null
+#include "c_generator.h"
+
+#include "node_internal.h"
+#include "node_type.h"
+
+#include <stdbool.h>
+
+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 "<unknown>"; // 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 "--";
+ }
+}
--- /dev/null
+#ifndef C_GENERATOR_H
+#define C_GENERATOR_H
+
+#include "node.h"
+#include <stdio.h>
+
+extern int c_generator_generate_module(FILE *output_file, Node *module);
+
+#endif
--- /dev/null
+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})
--- /dev/null
+#include <sun/compiler/compiler_internal.h>
+
+#include <stdio.h>
+
+#include "sun_parser.h" // This needs to be first.
+#include "sun_lexer.h"
+
+#include <sun/compiler/vm_generator.h>
+#include <sun/tree/node.h>
+#include <sun/tree/tree.h>
+#include <sun/vm/vm.h>
+
+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;
+ }
+}
--- /dev/null
+#ifndef SUN_COMPILER_COMPILER_H
+#define SUN_COMPILER_COMPILER_H
+
+#include <sun/vm/vm.h>
+#include <stddef.h>
+
+#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
--- /dev/null
+#ifndef SUN_COMPILER_COMPILER_INTERNAL_H
+#define SUN_COMPILER_COMPILER_INTERNAL_H
+
+#include <sun/compiler/compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct SLCLexerExtra {
+ SLCSourceReadCallback readCallback;
+ void *readCallbackParameter;
+};
+typedef struct SLCLexerExtra SLCLexerExtra;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+%{
+ #define YYSTYPE SLTNode *
+ #define YY_USER_ACTION yyadvancelocation(yylloc, yyleng, yytext);
+
+ #include <sun/compiler/compiler_internal.h>
+ #include <sun/tree/node.h>
+ #include "sun_parser.h"
+
+ #include <stdbool.h>
+ #include <stdio.h>
+
+ 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); }
+<SL_COMMENT>\n { BEGIN(INITIAL); }
+<SL_COMMENT>. ; /* Eat comments */
+
+"/*" { BEGIN(ML_COMMENT); }
+<ML_COMMENT>"*/" { BEGIN(INITIAL); }
+<ML_COMMENT>\n ; /* Eat comments */
+<ML_COMMENT>. ; /* 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;
+ }
+ }
+}
--- /dev/null
+%{
+ #define YYSTYPE SLTNode *
+
+ #include <sun/compiler/compiler_internal.h>
+ #include <sun/tree/node.h>
+
+ #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);
+}
--- /dev/null
+#include "vm_generator.h"
+
+#include <sun/tree/node_internal.h>
+#include <sun/tree/node_type.h>
+#include <sun/tree/tree.h>
+#include <sun/vm/instruction.h>
+#include <sun/vm/vm_internal.h>
+
+
+#include <stdarg.h> //fixme
+#include <stdbool.h> //fixme
+#include <stdlib.h> //fixme
+#include <stdio.h> //fixme
+#include <string.h> //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;
+}
--- /dev/null
+#ifndef SUN_COMPILER_VM_GENERATOR_H
+#define SUN_COMPILER_VM_GENERATOR_H
+
+#include <sun/tree/node.h>
+#include <sun/vm/vm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern SVMModule *slcGenerateVMInstructions(SLTNode *moduleNode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+#ifndef SUN_TREE_CRC32_H
+#define SUN_TREE_CRC32_H
+
+#include <stdint.h>
+
+#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
--- /dev/null
+#include "data_type.h"
+
+const char *sltDataTypeToString(SLTDataType dataType) {
+ switch(dataType) {
+ default:
+ case SLTDataTypeUnknown:
+ return "<unknown>";
+
+ case SLTDataTypeNone:
+ return "None";
+
+ case SLTDataTypeBoolean:
+ return "Boolean";
+
+ case SLTDataTypeInteger:
+ return "Integer";
+
+ case SLTDataTypeFloat:
+ return "Float";
+
+ case SLTDataTypeString:
+ return "String";
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#include "node_internal.h"
+
+#include <sun/tree/crc32.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+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;
+}
--- /dev/null
+#ifndef SUN_TREE_NODE_H
+#define SUN_TREE_NODE_H
+
+#include <sun/tree/operator_type.h>
+#include <stdbool.h>
+
+#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
--- /dev/null
+#ifndef SUN_TREE_NODE_INTERNAL_H
+#define SUN_TREE_NODE_INTERNAL_H
+
+#include <sun/tree/node.h>
+
+#include <sun/tree/data_type.h>
+#include <sun/tree/node_type.h>
+#include <stdbool.h>
+
+#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
--- /dev/null
+#include "node_type.h"
+
+const char *sltNodeTypeToString(SLTNodeType nodeType) {
+ switch(nodeType) {
+ default:
+ case SLTNodeTypeUnknown:
+ return "<unknown>";
+
+ 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";
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#include "operator_type.h"
+
+const char *sltOperatorTypeToString(SLTOperatorType operatorType) {
+ switch (operatorType) {
+ default:
+ case SLTOperatorTypeUnknown:
+ return "<unknown>";
+
+ 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";*/
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#include "tree.h"
+
+#include "node_internal.h"
+#include "node_type.h"
+
+#include <stdlib.h>
+
+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;
+}
--- /dev/null
+#ifndef SUN_TREE_TREE_H
+#define SUN_TREE_TREE_H
+
+#include <sun/tree/node.h>
+
+#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
--- /dev/null
+#include "fixed.h"
+
+#include <math.h>
+
+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);
+}
--- /dev/null
+#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 <assert.h>
+#include <stdint.h>
+
+#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
--- /dev/null
+#include <sun/vm/instruction.h>
+
+#include <assert.h>
+
+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 "<invalid>";
+
+ 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";
+ }
+}
--- /dev/null
+#ifndef SUN_VM_INSTRUCTION_H
+#define SUN_VM_INSTRUCTION_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sun/vm/fixed.h>
+
+#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
--- /dev/null
+#include "vm_internal.h"
+
+#include <string.h> // memcpy
+#include <stdio.h> // printf, fixme, remove
+#include <math.h> // 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) {
+
+}
--- /dev/null
+#ifndef SUN_VM_VM_H
+#define SUN_VM_VM_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sun/vm/instruction.h>
+
+#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
--- /dev/null
+#ifndef SUN_VM_VM_INTERNAL_H
+#define SUN_VM_VM_INTERNAL_H
+
+#include <sun/vm/vm.h>
+
+#include <sun/vm/instruction.h>
+#include <stdint.h>
+
+#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
--- /dev/null
+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})
--- /dev/null
+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