crepl

An intuitive calculator REPL.
git clone git://git.knutsen.co/crepl
Log | Files | Refs | README | LICENSE

commit bc8f596c1afb35571a18a5c6bd1abf2110248e6c
parent 698df4516bb7a9224a726dc5117ae60ae156d21a
Author: Demonstrandum <moi@knutsen.co>
Date:   Thu, 25 Jun 2020 12:52:49 +0100

Added dynamically growable local variable store, added prelude file, define many more functions and constants, fix memeory bugs.

Diffstat:
MMakefile | 11+++++++----
MREADME.md | 4++++
Msrc/builtin.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/builtin.h | 62+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Asrc/defaults.c | 39+++++++++++++++++++++++++++++++++++++++
Csrc/prelude.h -> src/defaults.h | 0
Msrc/displays.c | 1-
Msrc/displays.h | 1+
Msrc/execute.c | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/execute.h | 14+++++++-------
Msrc/main.c | 2+-
Msrc/parse.c | 10++++++----
Msrc/parse.h | 8+++++---
Msrc/prelude.c | 51+++++++++++++++++++++------------------------------
Msrc/prelude.h | 76+++++-----------------------------------------------------------------------
15 files changed, 311 insertions(+), 168 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,7 +3,7 @@ OPT := -O3 WARN := -Wall -Wpedantic -Wextra -Wshadow -fcompare-debug-second CFLAGS := $(WARN) $(OPT) TARGET := crepl -OBJS := main.o prelude.o error.o parse.o displays.o builtin.o execute.o +OBJS := main.o defaults.o error.o parse.o displays.o builtin.o execute.o prelude.o LINKS := -lm -lreadline ifeq ($(PREFIX),) @@ -24,10 +24,13 @@ install: $(TARGET) install -d $(PREFIX)/bin install -m 755 $(TARGET) $(PREFIX)/bin -main.o: prelude.o parse.o error.o +main.o: defaults.o parse.o error.o $(CC) -c $(CFLAGS) src/main.c -prelude.o: error.o +defaults.o: error.o + $(CC) -c $(CFLAGS) src/defaults.c + +prelude.o: $(CC) -c $(CFLAGS) src/prelude.c parse.o: error.o @@ -39,7 +42,7 @@ displays.o: parse.o builtin.o: $(CC) -c $(CFLAGS) src/builtin.c -execute.o: parse.o error.o +execute.o: parse.o error.o prelude.o $(CC) -c $(CFLAGS) src/execute.c error.o: diff --git a/README.md b/README.md @@ -26,3 +26,7 @@ make # Builds and compiles the project. sudo make install # Installs the program system wide. ``` +## TODO + - [ ] User defined functions. + - [ ] Garbage collection. + - [ ] Extend numbers to include “Big Numbers” (“Big Integers” and “Big Decimals”/Rationals), numbers a currently limited to ~80bit floats and pointer-sized (likely 64bit) integeres. diff --git a/src/builtin.c b/src/builtin.c @@ -1,3 +1,4 @@ +#include "defaults.h" #include "builtin.h" NumberNode num_to_float(NumberNode num) @@ -75,21 +76,47 @@ NumberNode *upcast_pair(NumberNode lhs, NumberNode rhs) return pair; } -DataValue *builtin_sin(DataValue input) -{ - NumberNode *num = type_check("sin", ARG, T_NUMBER, &input); - if (num == NULL) - return NULL; - DataValue *result = wrap_data(T_NUMBER, num); - - NumberNode tmp = num_to_float(*num); - memcpy(num, &tmp, sizeof(NumberNode)); - num->value.f = sin(num->value.f); - num->type = FLOAT; - result->value = num; - return result; +#define MATH_WRAPPER(NAME, FUNC)\ +DataValue *builtin_ ##NAME (DataValue input) \ +{ \ + NumberNode *num = type_check(#NAME, ARG, T_NUMBER, &input); \ + \ + if (num == NULL) \ + return NULL; \ + \ + NumberNode *new_num = malloc(sizeof(NumberNode)); \ + \ + NumberNode tmp = num_to_float(*num); \ + tmp.value.f = FUNC(tmp.value.f); \ + \ + memcpy(new_num, &tmp, sizeof(NumberNode)); \ + DataValue *result = wrap_data(T_NUMBER, new_num); \ + return result; \ } +MATH_WRAPPER(sin, sinl) +MATH_WRAPPER(sinh, sinhl) +MATH_WRAPPER(cos, cosl) +MATH_WRAPPER(cosh, coshl) +MATH_WRAPPER(tan, tanl) +MATH_WRAPPER(tanh, tanhl) +MATH_WRAPPER(exp, expl) +MATH_WRAPPER(abs, fabsl) +MATH_WRAPPER(log, log10l) +MATH_WRAPPER(log2, log2l) +MATH_WRAPPER(ln, logl) +MATH_WRAPPER(sqrt, sqrtl) +MATH_WRAPPER(cbrt, cbrtl) +MATH_WRAPPER(acos, acosl) +MATH_WRAPPER(acosh, acoshl) +MATH_WRAPPER(asin, asinl) +MATH_WRAPPER(asinh, asinhl) +MATH_WRAPPER(atan, atanl) +MATH_WRAPPER(atanh, atanhl) +// TODO: atan2, hypot +MATH_WRAPPER(ceil, ceil) +MATH_WRAPPER(floor, floor) + DataValue *builtin_factorial(DataValue input) { NumberNode *num = type_check("!", LHS, T_NUMBER, &input); @@ -103,28 +130,24 @@ DataValue *builtin_factorial(DataValue input) } NumberNode tmp = num_to_int(*num); - memcpy(num, &tmp, sizeof(NumberNode)); + NumberNode *new_num = malloc(sizeof(NumberNode)); + memcpy(new_num, &tmp, sizeof(NumberNode)); - DataValue *result = wrap_data(T_NUMBER, num); - if (num->value.i == 0) { - num->value.i = 1; - result->value = num; + DataValue *result = wrap_data(T_NUMBER, new_num); + if (new_num->value.i == 0) { + new_num->value.i = 1; + result->value = new_num; return result; } - ssize i = num->value.i - 1; + ssize i = new_num->value.i - 1; while (i > 1) { - num->value.i *= i; + new_num->value.i *= i; --i; } - result->value = num; + result->value = new_num; return result; } -FnPtr builtin_fns[] = { - { builtin_sin }, - { builtin_factorial }, -}; - #define BINARY_FUNCTION(NAME, OP) \ NumberNode *num_ ## NAME (NumberNode lhs, NumberNode rhs) \ { \ @@ -163,3 +186,31 @@ NumberNode *num_div(NumberNode lhs, NumberNode rhs) result->value.f = num_to_float(lhs).value.f / num_to_float(rhs).value.f; return result; } + +NumberNode *num_pow(NumberNode lhs, NumberNode rhs) +{ + NumberNode *upcasted = upcast_pair(lhs, rhs); + if (upcasted == NULL) + return NULL; + + NumberNode *result = upcasted + 0; + + switch (result->type) { + case FLOAT: + result->value.f = powl(upcasted[0].value.f, upcasted[1].value.f); + break; + case INT: + result->value.i = upcasted[1].value.i < 0 + ? ((fsize)1) / ipow(upcasted[0].value.i, -upcasted[1].value.i) + : ipow(upcasted[0].value.i, upcasted[1].value.i); + break; + default: { + ERROR_TYPE = EXECUTION_ERROR; + strcpy(ERROR_MSG, "Unsupported number type."); + return NULL; + } + } + result = realloc(result, sizeof(NumberNode)); + return result; +} + diff --git a/src/builtin.h b/src/builtin.h @@ -2,7 +2,7 @@ #include <math.h> -#include "prelude.h" +#include "defaults.h" #include "parse.h" #include "execute.h" #include "error.h" @@ -12,11 +12,67 @@ NumberNode num_to_int(NumberNode); NumberNode *upcast_pair(NumberNode, NumberNode); DataValue *builtin_sin(DataValue); - -extern FnPtr builtin_fns[]; +DataValue *builtin_sinh(DataValue); +DataValue *builtin_cos(DataValue); +DataValue *builtin_cosh(DataValue); +DataValue *builtin_tan(DataValue); +DataValue *builtin_tanh(DataValue); +DataValue *builtin_exp(DataValue); +DataValue *builtin_abs(DataValue); +DataValue *builtin_log(DataValue); +DataValue *builtin_log2(DataValue); +DataValue *builtin_ln(DataValue); +DataValue *builtin_sqrt(DataValue); +DataValue *builtin_cbrt(DataValue); +DataValue *builtin_acos(DataValue); +DataValue *builtin_acosh(DataValue); +DataValue *builtin_asin(DataValue); +DataValue *builtin_asinh(DataValue); +DataValue *builtin_atan(DataValue); +DataValue *builtin_atanh(DataValue); +DataValue *builtin_factorial(DataValue); NumberNode *num_add(NumberNode, NumberNode); NumberNode *num_sub(NumberNode, NumberNode); NumberNode *num_mul(NumberNode, NumberNode); NumberNode *num_div(NumberNode, NumberNode); +NumberNode *num_pow(NumberNode, NumberNode); + +#define FUNC_PAIR(NAME) { #NAME, { builtin_##NAME } } + +struct _func_name_pair { + char *name; + FnPtr function; +}; + +static const struct _func_name_pair builtin_fns[] = { + FUNC_PAIR(sin), + FUNC_PAIR(sinh), + FUNC_PAIR(cos), + FUNC_PAIR(cosh), + FUNC_PAIR(tan), + FUNC_PAIR(tanh), + FUNC_PAIR(exp), + FUNC_PAIR(abs), + FUNC_PAIR(log), + { "log10", { builtin_log } }, + FUNC_PAIR(log2), + FUNC_PAIR(ln), + FUNC_PAIR(sqrt), + FUNC_PAIR(cbrt), + FUNC_PAIR(acos), + { "arccos", { builtin_acos } }, + FUNC_PAIR(acosh), + { "arccosh", { builtin_acosh } }, + FUNC_PAIR(asin), + { "arcsin", { builtin_asin } }, + FUNC_PAIR(asinh), + { "arcsinh", { builtin_asinh } }, + FUNC_PAIR(atan), + { "arctan", { builtin_atan } }, + FUNC_PAIR(atanh), + { "arctanh", { builtin_atanh } }, + FUNC_PAIR(factorial), + { "!", { builtin_factorial } }, +}; diff --git a/src/defaults.c b/src/defaults.c @@ -0,0 +1,39 @@ +#include "defaults.h" + +ssize ipow(ssize base, usize exp) +{ + ssize result = 1; + do { + if (exp & 1) + result *= base; + exp >>= 1; + if (!exp) + break; + base *= base; + } while (true); + + return result; +} + +char *trim(char *str) +{ + char *p = strdup(str); + while (isspace(*p)) + ++p; + + char *end = p + strlen(p) - 1; + while (end > p && isspace(*end)) + --end; + + *(end + 1) = '\0'; + return p; +} + + +char *downcase(char *str) +{ + char *p = strdup(str); + char *start = p; + for (; *p; ++p) *p = tolower(*p); + return start; +} diff --git a/src/prelude.h b/src/defaults.h diff --git a/src/displays.c b/src/displays.c @@ -3,7 +3,6 @@ #include <string.h> #include <wchar.h> -#include "prelude.h" #include "parse.h" #include "execute.h" #include "displays.h" diff --git a/src/displays.h b/src/displays.h @@ -1,3 +1,4 @@ +#include "defaults.h" #include "parse.h" #include "execute.h" diff --git a/src/execute.c b/src/execute.c @@ -2,13 +2,16 @@ #include "error.h" #include "parse.h" #include "builtin.h" +#include "prelude.h" #include "displays.h" #include <math.h> +static const f32 LOCALS_REALLOC_GROWTH_FACTOR = 1.5; + #define NUMERICAL_BINARY_OPERATION(OPERATION) do { \ - NumberNode *l_num = type_check("+", LHS, T_NUMBER, lhs); \ - NumberNode *r_num = type_check("+", RHS, T_NUMBER, rhs); \ + NumberNode *l_num = type_check(op, LHS, T_NUMBER, lhs); \ + NumberNode *r_num = type_check(op, RHS, T_NUMBER, rhs); \ if (l_num == NULL || r_num == NULL) \ return NULL; \ data->type = T_NUMBER; \ @@ -96,11 +99,29 @@ finished_search: strcpy(ERROR_MSG, "Binary operation has non-ident callee."); return NULL; } - // How to evaluate specific operators. + char *op = ident.value; + // Equality is special: + if (strcmp(op, "=") == 0) { + // TODO: Add support for assignment of functions? + if (stmt->node.binary.left->type != IDENT_NODE) { + ERROR_TYPE = PARSE_ERROR; + strcpy(ERROR_MSG, "Left of assignment (`=') operator\n" + " must be an identifier/variable."); + return NULL; + } + char *lvalue = stmt->node.binary.left->node.ident.value; + free(data); + data = execute(ctx, stmt->node.binary.right); + bind_local(ctx, lvalue, data->type, data->value); + break; + } + + // How to evaluate specific operators. DataValue *lhs = execute(ctx, stmt->node.binary.left); DataValue *rhs = execute(ctx, stmt->node.binary.right); + // Numerical binary operations. if (strcmp(op, "+") == 0) { NUMERICAL_BINARY_OPERATION(add); } else if (strcmp(op, "-") == 0) { @@ -109,6 +130,8 @@ finished_search: NUMERICAL_BINARY_OPERATION(mul); } else if (strcmp(op, "/") == 0) { NUMERICAL_BINARY_OPERATION(div); + } else if (strcmp(op, "^") * strcmp(op, "**") == 0) { + NUMERICAL_BINARY_OPERATION(pow); } else { ERROR_TYPE = EXECUTION_ERROR; sprintf(ERROR_MSG, "Do not know how to evaluate" @@ -135,13 +158,13 @@ DataValue *wrap_data(DataType type, void *value) return data; } -void *type_check(char *function_name, ParamPos pos, - DataType type, DataValue *value) +void *type_check(const char *function_name, ParamPos pos, + DataType type, const DataValue *value) { if (value != NULL && value->value != NULL && value->type == type) - return value->value; + return (void *)value->value; ERROR_TYPE = TYPE_ERROR; sprintf(ERROR_MSG, "Wrong type for %s of `%s' operation,\n" @@ -155,32 +178,68 @@ void *type_check(char *function_name, ParamPos pos, return NULL; } -Local *make_local(char *name, DataType type, void *value) +Local *make_local(const char *name, DataType type, void *value) { Local *local = malloc(sizeof(Local)); - local->name = name; + local->name = strdup(name); local->value.type = type; local->value.value = value; return local; } -void bind_local(Context *ctx, char *name, DataType type, void *value) +// Locals is a dynamically growable array. +void bind_local(Context *ctx, const char *name, + DataType type, void *value) { + // Check capacity. + if (ctx->locals_count == ctx->locals_capacity) { + // Grow array. + ctx->locals_capacity *= LOCALS_REALLOC_GROWTH_FACTOR; + ctx->locals = realloc(ctx->locals, + sizeof(Local) * ctx->locals_capacity); + } + + // Check if it already exists. + Local *local_ptr = NULL; + for (usize i = 0; i < ctx->locals_count; ++i) { + Local *l = ctx->locals + i; + if (strcmp(l->name, name) == 0) { + local_ptr = l; + break; + } + } + Local *local = make_local(name, type, value); + + if (local_ptr != NULL) { + *local_ptr = *local; + return; + } + ctx->locals[ctx->locals_count] = *local; ++ctx->locals_count; } void bind_builtin_functions(Context *ctx) { - bind_local(ctx, "sin", T_FUNCTION_PTR, &builtin_fns[0]); - bind_local(ctx, "!", T_FUNCTION_PTR, &builtin_fns[1]); + for (usize i = 0; i < len(builtin_fns); ++i) { + struct _func_name_pair *pair = + (struct _func_name_pair *)(builtin_fns + i); + bind_local(ctx, pair->name, T_FUNCTION_PTR, &pair->function); + } } void bind_default_globals(Context *ctx) { fsize pi = M_PI; + fsize e = M_E; + fsize inf = HUGE_VAL; + fsize nan = NAN; + bind_local(ctx, "pi", T_NUMBER, make_number(FLOAT, &pi)); + bind_local(ctx, "e", T_NUMBER, make_number(FLOAT, &e)); + bind_local(ctx, "inf", T_NUMBER, make_number(FLOAT, &inf)); + bind_local(ctx, "nan", T_NUMBER, make_number(FLOAT, &nan)); } Context *init_context() @@ -189,17 +248,17 @@ Context *init_context() ctx->superior = NULL; // There is no context superior to this one. ctx->function = "<main>"; // Main function/scope. - // Initialise with 16 free spaces for local variables. - // This may have to be reallocated if more than 16 + // Initialise with 6 free spaces for local variables. + // This may have to be reallocated if more than 6 // variables need to exist :^). ctx->locals_count = 1; - ctx->locals_capacity = 16; + ctx->locals_capacity = 6; ctx->locals = malloc(sizeof(Local) * ctx->locals_capacity); // Create an initial local varaible with the value of the // name of the function/scope. Local *scope_name = make_local( - "__this_scope", T_STRING, ctx->function); + "__this_scope", T_STRING, (void *)ctx->function); ctx->locals[0] = *scope_name; // ^ Sets the first variable, default in every scope // (good for debuggin purposes). @@ -210,12 +269,14 @@ Context *init_context() Context *base_context() { Context *ctx = init_context(); - bind_default_globals(ctx); - bind_builtin_functions(ctx); + bind_default_globals(ctx); // Global variables. + bind_builtin_functions(ctx); // Interface with certain C functions. + // Load the "prelude" library, runs at start of every base context: + execute_prelude(ctx); return ctx; } -Context *make_context(char *scope_name, Context *super_scope) +Context *make_context(const char *scope_name, Context *super_scope) { Context *ctx = init_context(); ctx->function = scope_name; diff --git a/src/execute.h b/src/execute.h @@ -1,6 +1,6 @@ #pragma once -#include "prelude.h" +#include "defaults.h" #include "parse.h" typedef enum { @@ -22,7 +22,7 @@ typedef struct { } FnPtr; typedef struct { - char *name; + const char *name; DataValue value; } Local; @@ -30,7 +30,7 @@ struct _context; typedef struct _context { struct _context *superior; - char *function; + const char *function; // `locals` works as a dynamic array; usize locals_count; usize locals_capacity; @@ -42,12 +42,12 @@ typedef enum { } ParamPos; void free_datavalue(DataValue *); -void *type_check(char *, ParamPos, DataType, DataValue *); +void *type_check(const char *, ParamPos, DataType, const DataValue *); DataValue *execute(Context *, const ParseNode *); DataValue *wrap_data(DataType, void *); -Local *make_local(char *, DataType, void *); -void bind_local(Context *, char *name, DataType, void*); +Local *make_local(const char *, DataType, void *); +void bind_local(Context *, const char *, DataType, void *); void bind_builtin_functions(Context *); Context *init_context(); Context *base_context(); -Context *make_context(char *, Context *); +Context *make_context(const char *, Context *); diff --git a/src/main.c b/src/main.c @@ -8,7 +8,7 @@ #include <readline/readline.h> #include <readline/history.h> -#include "prelude.h" +#include "defaults.h" #include "error.h" #include "parse.h" #include "execute.h" diff --git a/src/parse.c b/src/parse.c @@ -1,5 +1,3 @@ -#include "prelude.h" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -500,7 +498,11 @@ ParseNode *parse_expr(char **slice, u16 precedence) return left; } -ParseNode *parse(char *source) +ParseNode *parse(const char *source) { - return parse_expr(&source, 0); + char *stepper = strdup(source); + char *start = stepper; + ParseNode *tree = parse_expr(&stepper, 0); + free(start); + return tree; } diff --git a/src/parse.h b/src/parse.h @@ -1,5 +1,7 @@ #pragma once +#include "defaults.h" + // Tokens: typedef enum { TT_LPAREN, TT_RPAREN, @@ -42,7 +44,7 @@ static const Operator KNOWN_OPERATORS[] = { // 3 characters long. { "not", 8, RIGHT_ASSOC, PREFIX }, // 2 characters long. - { "**", 7, RIGHT_ASSOC, INFIX }, + { "**", 10, RIGHT_ASSOC, INFIX }, { "<=", 4, LEFT_ASSOC, INFIX }, { ">=", 4, LEFT_ASSOC, INFIX }, { "==", 3, LEFT_ASSOC, INFIX }, @@ -52,7 +54,7 @@ static const Operator KNOWN_OPERATORS[] = { { "+", 10, RIGHT_ASSOC, PREFIX }, { "¬", 10, RIGHT_ASSOC, PREFIX }, { "!", 10, LEFT_ASSOC, POSTFIX }, - { "^", 7, RIGHT_ASSOC, INFIX }, + { "^", 10, RIGHT_ASSOC, INFIX }, { "*", 6, LEFT_ASSOC, INFIX }, { "/", 6, LEFT_ASSOC, INFIX }, { "+", 5, LEFT_ASSOC, INFIX }, @@ -128,4 +130,4 @@ NumberNode *parse_number(const char *); ParseNode *parse_prefix(const Token *, char **); ParseNode *parse_infix(const ParseNode *, const Token *, char **, u16); ParseNode *parse_expr(char **, u16); -ParseNode *parse(char *); +ParseNode *parse(const char *); diff --git a/src/prelude.c b/src/prelude.c @@ -1,39 +1,30 @@ #include "prelude.h" -ssize ipow(ssize base, usize exp) -{ - ssize result = 1; - do { - if (exp & 1) - result *= base; - exp >>= 1; - if (!exp) - break; - base *= base; - } while (true); - - return result; -} +char *PRELUDE_STATEMENTS[] = { + "tau = 2pi", + "phi = 1.61803398875", +}; -char *trim(char *str) +void execute_prelude(Context *ctx) { - char *p = strdup(str); - while (isspace(*p)) - ++p; + for (usize i = 0; i < len(PRELUDE_STATEMENTS); ++i) { + const char *stmt_str = PRELUDE_STATEMENTS[i]; - char *end = p + strlen(p) - 1; - while (end > p && isspace(*end)) - --end; + ParseNode *stmt = parse(stmt_str); + if (stmt == NULL || ERROR_TYPE != NO_ERROR) + goto fatality; - *(end + 1) = '\0'; - return p; -} + DataValue *result = execute(ctx, stmt); + if (result == NULL || ERROR_TYPE != NO_ERROR) + goto fatality; + free(stmt); + } + return; -char *downcase(char *str) -{ - char *p = strdup(str); - char *start = p; - for (; *p; ++p) *p = tolower(*p); - return start; +fatality: + handle_error(); + fprintf(stderr, "\nFATAL: Prelude failed to run without error.\n"); + fprintf(stderr, "ABORTING\n!"); + exit(1); } diff --git a/src/prelude.h b/src/prelude.h @@ -1,73 +1,7 @@ -#pragma once - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <stddef.h> -#include <stdbool.h> -#include <string.h> -#include <ctype.h> - +#include "defaults.h" #include "error.h" +#include "parse.h" +#include "execute.h" -#define len(array) (sizeof(array) / sizeof((array)[0])) - -typedef uint8_t u8 ; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8 ; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -typedef size_t usize; -typedef ptrdiff_t ssize; - -typedef float f32; -typedef double f64; -typedef long double fsize; - -ssize ipow(ssize, usize); - -char *trim(char *); -char *downcase(char *); - -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) - -// Check windows -#if defined(_WIN32) || defined(_WIN64) - #ifdef _WIN64 - #define ARCH64 - #else - #define ARCH32 - #endif -#endif - -// Check GCC -#ifdef __GNUC__ - #if defined(__x86_64__) || defined(__ppc64__) - #define ARCH64 - #else - #define ARCH32 - #endif -#endif - -#if defined(_MSC_VER) - #define COMPILER "Visual Studio " STR(VS) -#elif defined(__GNUC__) - #define COMPILER "GCC " STR(__GNUC__) "." STR(__GNUC_MINOR__) -#elif defined(__clang__) - #define COMPILER "Clang " STR(__clang_major__) "." STR(__clang_minor__) -#elif defined(__EMSCRIPTEN__) - #define COMPILER "WebAssembly " STR(__EMSCRIPTEN__) -#elif defined(__MINGW32__) - #define COMPILER "MinGW 32bit " STR(__MINGW32__) -#elif defined(__MINGW64__) - #define COMPILER "MinGW 64bit " STR(__MINGW64__) -#else - #define COMPILER "Unknown Compiler" -#endif - +extern char *PRELUDE_STATEMENTS[]; +void execute_prelude(Context *);