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:
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 *);