src/system/line_stream.h
src/system/log.c
src/system/log.h
- src/system/log_script.c
- src/system/log_script.h
src/system/lt.h
src/system/lt_adapters.h
src/system/lt_adapters.c
src/system/file.c
)
-add_library(ebisp STATIC
- src/ebisp/builtins.c
- src/ebisp/builtins.h
- src/ebisp/expr.c
- src/ebisp/expr.h
- src/ebisp/gc.c
- src/ebisp/gc.h
- src/ebisp/interpreter.c
- src/ebisp/interpreter.h
- src/ebisp/parser.c
- src/ebisp/parser.h
- src/ebisp/scope.c
- src/ebisp/scope.h
- src/ebisp/std.c
- src/ebisp/std.h
- src/ebisp/tokenizer.c
- src/ebisp/tokenizer.h
- )
-target_link_libraries(ebisp system)
-
add_executable(nothing
- src/broadcast.c
- src/broadcast.h
src/color.c
src/color.h
src/game.c
src/game/level/regions.h
src/game/level/rigid_bodies.c
src/game/level/rigid_bodies.h
- src/game/level/script.c
- src/game/level/script.h
src/game/level_picker.c
src/game/level_picker.h
src/game/level_folder.h
src/game/level/level_editor/undo_history.h
src/game/level/level_editor/undo_history.c
)
-target_link_libraries(nothing ${SDL2_LIBRARIES} system ebisp)
-
-add_executable(repl
- src/ebisp/repl.c
- src/ebisp/repl_runtime.c
- )
-target_link_libraries(repl ${SDL2_LIBRARIES} system ebisp)
-
-add_executable(nothing_test
- test/main.c
- test/test.h
- test/tokenizer_suite.h
- )
-target_link_libraries(nothing_test ${SDL2_LIBRARIES} system ebisp)
+target_link_libraries(nothing ${SDL2_LIBRARIES} system)
if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
set(CMAKE_C_FLAGS
elseif(WIN32)
target_link_libraries(nothing Imm32 Version winmm)
endif()
-
-file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test-data DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+++ /dev/null
-#include <stdlib.h>
-#include <string.h>
-
-#include "system/stacktrace.h"
-#include "system/nth_alloc.h"
-#include "broadcast.h"
-#include "ebisp/interpreter.h"
-#include "ebisp/expr.h"
-#include "ebisp/scope.h"
-#include "game.h"
-
-struct EvalResult
-unknown_target(Gc *gc, const char *source, const char *target)
-{
- return eval_failure(
- list(gc, "qqq", "unknown-target", source, target));
-}
-
-static struct EvalResult
-send(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(param);
- trace_assert(gc);
- trace_assert(scope);
-
- Broadcast *broadcast = (Broadcast*) param;
-
- struct Expr path = void_expr();
- struct EvalResult result = match_list(gc, "e", args, &path);
- if (result.is_error) {
- return result;
- }
-
- return broadcast_send(broadcast, gc, scope, path);
-}
-
-struct Broadcast
-{
- Game *game;
-};
-
-Broadcast *create_broadcast(Game *game)
-{
- trace_assert(game);
-
- Broadcast *broadcast = nth_calloc(1, sizeof(Broadcast));
- if (broadcast == NULL) {
- return NULL;
- }
-
- broadcast->game = game;
-
- return broadcast;
-}
-
-void destroy_broadcast(Broadcast *broadcast)
-{
- trace_assert(broadcast);
- free(broadcast);
-}
-
-struct EvalResult
-broadcast_send(Broadcast *broadcast,
- Gc *gc,
- struct Scope *scope,
- struct Expr path)
-{
- trace_assert(broadcast);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "q*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- if (strcmp(target, "game") == 0) {
- return game_send(broadcast->game, gc, scope, rest);
- }
-
- return unknown_target(gc, "game", target);
-}
-
-void broadcast_load_library(Broadcast *broadcast,
- Gc *gc,
- struct Scope *scope)
-{
- trace_assert(gc);
- trace_assert(scope);
- trace_assert(broadcast);
-
- set_scope_value(gc, scope, SYMBOL(gc, "send"), NATIVE(gc, send, broadcast));
-}
+++ /dev/null
-#ifndef BROADCAST_H_
-#define BROADCAST_H_
-
-#include "ebisp/expr.h"
-
-typedef struct Broadcast Broadcast;
-typedef struct Game Game;
-
-Broadcast *create_broadcast(Game *game);
-void destroy_broadcast(Broadcast *broadcast);
-
-struct EvalResult
-broadcast_send(Broadcast *broadcast,
- Gc *gc,
- struct Scope *scope,
- struct Expr path);
-
-void broadcast_load_library(Broadcast *broadcast,
- Gc *gc,
- struct Scope *scope);
-
-struct EvalResult
-unknown_target(Gc *gc, const char *source, const char *target);
-
-#endif // BROADCAST_H_
#ifndef DYNARRAY_H_
#define DYNARRAY_H_
+#include <stdlib.h>
#include <stdbool.h>
typedef struct Dynarray Dynarray;
+++ /dev/null
-#include "system/stacktrace.h"
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "builtins.h"
-
-static bool equal_atoms(struct Atom *atom1, struct Atom *atom2)
-{
- trace_assert(atom1);
- trace_assert(atom2);
-
- if (atom1->type != atom2->type) {
- return false;
- }
-
- switch (atom1->type) {
- case ATOM_SYMBOL: {
- return strcmp(atom1->sym, atom2->sym) == 0;
- }
-
- case ATOM_INTEGER: {
- return atom1->num == atom2->num;
- }
-
- case ATOM_REAL: {
- return atom1->real == atom2->real;
- }
-
- case ATOM_STRING: {
- return strcmp(atom1->str, atom2->str) == 0;
- }
-
- case ATOM_LAMBDA: {
- return atom1 == atom2;
- }
-
- case ATOM_NATIVE: {
- return atom1->native.fun == atom2->native.fun
- && atom1->native.param == atom2->native.param;
- }
- }
-
- return false;
-}
-
-static bool equal_cons(struct Cons *cons1, struct Cons *cons2)
-{
- trace_assert(cons1);
- trace_assert(cons2);
- return equal(cons1->car, cons2->car) && equal(cons1->cdr, cons2->cdr);
-}
-
-bool equal(struct Expr obj1, struct Expr obj2)
-{
- if (obj1.type != obj2.type) {
- return false;
- }
-
- switch (obj1.type) {
- case EXPR_ATOM:
- return equal_atoms(obj1.atom, obj2.atom);
-
- case EXPR_CONS:
- return equal_cons(obj1.cons, obj2.cons);
-
- case EXPR_VOID:
- return true;
- }
-
- return true;
-}
-
-bool nil_p(struct Expr obj)
-{
- return symbol_p(obj)
- && strcmp(obj.atom->sym, "nil") == 0;
-}
-
-
-bool symbol_p(struct Expr obj)
-{
- return obj.type == EXPR_ATOM
- && obj.atom->type == ATOM_SYMBOL;
-}
-
-bool integer_p(struct Expr obj)
-{
- return obj.type == EXPR_ATOM
- && obj.atom->type == ATOM_INTEGER;
-}
-
-bool string_p(struct Expr obj)
-{
- return obj.type == EXPR_ATOM
- && obj.atom->type == ATOM_STRING;
-}
-
-bool cons_p(struct Expr obj)
-{
- return obj.type == EXPR_CONS;
-}
-
-bool list_p(struct Expr obj)
-{
- if (nil_p(obj)) {
- return true;
- }
-
- if (obj.type == EXPR_CONS) {
- return list_p(obj.cons->cdr);
- }
-
- return false;
-}
-
-bool list_of_symbols_p(struct Expr obj)
-{
- if (nil_p(obj)) {
- return true;
- }
-
- if (obj.type == EXPR_CONS && symbol_p(obj.cons->car)) {
- return list_of_symbols_p(obj.cons->cdr);
- }
-
- return false;
-}
-
-bool lambda_p(struct Expr obj)
-{
- return obj.type == EXPR_ATOM
- && obj.atom->type == ATOM_LAMBDA;
-}
-
-long int length_of_list(struct Expr obj)
-{
- long int count = 0;
-
- while (!nil_p(obj)) {
- count++;
- obj = obj.cons->cdr;
- }
-
- return count;
-}
-
-struct Expr assoc(struct Expr key, struct Expr alist)
-{
- while (cons_p(alist)) {
- if (cons_p(CAR(alist)) && equal(CAR(CAR(alist)), key)) {
- return CAR(alist);
- }
-
- alist = CDR(alist);
- }
-
- return alist;
-}
-
-const char *specials[] = {
- "set", "quote", "begin",
- "defun", "lambda", "λ",
- "when", "quasiquote"
-};
-
-bool is_special(const char *name)
-{
- trace_assert(name);
-
- size_t n = sizeof(specials) / sizeof(const char*);
- for (size_t i = 0; i < n; ++i) {
- if (strcmp(name, specials[i]) == 0) {
- return true;
- }
- }
-
- return false;
-}
-
-
-static struct Expr
-list_rec(Gc *gc, const char *format, va_list args)
-{
- trace_assert(gc);
- trace_assert(format);
-
- if (*format == 0) {
- return NIL(gc);
- }
-
- switch (*format) {
- case 'd': {
- long int p = va_arg(args, long int);
- return CONS(gc, INTEGER(gc, p),
- list_rec(gc, format + 1, args));
- }
-
- case 's': {
- const char* p = va_arg(args, const char*);
- return CONS(gc, STRING(gc, p),
- list_rec(gc, format + 1, args));
- }
-
- case 'q': {
- const char* p = va_arg(args, const char*);
- return CONS(gc, SYMBOL(gc, p),
- list_rec(gc, format + 1, args));
- }
-
- case 'e': {
- struct Expr p = va_arg(args, struct Expr);
- return CONS(gc, p, list_rec(gc, format + 1, args));
- }
-
- default: {
- fprintf(stderr, "Wrong format parameter: %c\n", *format);
- trace_assert(0);
- }
- }
-
- return NIL(gc);
-}
-
-struct Expr
-list(Gc *gc, const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- struct Expr result = list_rec(gc, format, args);
- va_end(args);
-
- return result;
-}
-
-struct Expr bool_as_expr(Gc *gc, bool condition)
-{
- return condition ? T(gc) : NIL(gc);
-}
+++ /dev/null
-#ifndef BUILTINS_H_
-#define BUILTINS_H_
-
-#include "expr.h"
-
-bool equal(struct Expr obj1, struct Expr obj2);
-
-bool nil_p(struct Expr obj);
-bool symbol_p(struct Expr obj);
-bool string_p(struct Expr obj);
-bool integer_p(struct Expr obj);
-bool cons_p(struct Expr obj);
-bool list_p(struct Expr obj);
-bool list_of_symbols_p(struct Expr obj);
-bool lambda_p(struct Expr obj);
-
-bool is_special(const char *name);
-
-long int length_of_list(struct Expr obj);
-
-struct Expr assoc(struct Expr key, struct Expr alist);
-
-struct Expr list(Gc *gc, const char *format, ...);
-
-struct Expr bool_as_expr(Gc *gc, bool condition);
-
-#endif // BUILTINS_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "ebisp/expr.h"
-#include "ebisp/gc.h"
-#include "system/str.h"
-
-struct Expr atom_as_expr(struct Atom *atom)
-{
- struct Expr expr = {
- .type = EXPR_ATOM,
- .atom = atom
- };
-
- return expr;
-}
-
-struct Expr cons_as_expr(struct Cons *cons)
-{
- struct Expr expr = {
- .type = EXPR_CONS,
- .cons = cons
- };
-
- return expr;
-}
-
-struct Expr void_expr(void)
-{
- struct Expr expr = {
- .type = EXPR_VOID
- };
-
- return expr;
-}
-
-void print_atom_as_sexpr(FILE *stream, struct Atom *atom)
-{
- trace_assert(atom);
-
- switch (atom->type) {
- case ATOM_SYMBOL: {
- fprintf(stream, "%s", atom->sym);
- } break;
-
- case ATOM_INTEGER: {
- fprintf(stream, "%ld", atom->num);
- } break;
-
- case ATOM_REAL: {
- fprintf(stream, "%f", atom->real);
- } break;
-
- case ATOM_STRING: {
- fprintf(stream, "\"%s\"", atom->str);
- } break;
-
- case ATOM_LAMBDA: {
- /* TODO(#649): Print LAMBDAs with arglists (and maybe bodies) in print_atom_as_sexpr and atom_as_sexpr */
- fprintf(stream, "<lambda>");
- } break;
-
- case ATOM_NATIVE: {
- fprintf(stream, "<native>");
- } break;
- }
-}
-
-static void print_atom_as_c(FILE *stream, struct Atom *atom)
-{
- trace_assert(stream);
- trace_assert(atom);
-
- switch(atom->type) {
- case ATOM_SYMBOL: {
- fprintf(stream, "SYMBOL(gc, \"%s\")", atom->sym);
- } break;
-
- case ATOM_INTEGER: {
- fprintf(stream, "INTEGER(gc, %ld)", atom->num);
- } break;
-
- case ATOM_REAL: {
- fprintf(stream, "REAL(gc, %f)", atom->real);
- } break;
-
- case ATOM_STRING: {
- fprintf(stream, "STRING(gc, \"%s\")", atom->str);
- } break;
-
- case ATOM_LAMBDA: {
- fprintf(stream, "CONS(gc, SYMBOL(gc, \"lambda\"), CONS(gc, ");
- print_expr_as_c(stream, atom->lambda.args_list);
- fprintf(stream, ", CONS(gc, ");
- print_expr_as_c(stream, atom->lambda.body);
- fprintf(stream, ")))");
- } break;
-
- case ATOM_NATIVE: {
- fprintf(stream, "NIL(gc)");
- } break;
- }
-}
-
-void print_cons_as_sexpr(FILE *stream, struct Cons *head)
-{
- trace_assert(head);
-
- struct Cons *cons = head;
-
- fprintf(stream, "(");
- print_expr_as_sexpr(stream, cons->car);
-
- while (cons->cdr.type == EXPR_CONS) {
- cons = cons->cdr.cons;
- fprintf(stream, " ");
- print_expr_as_sexpr(stream, cons->car);
- }
-
- if (cons->cdr.atom->type != ATOM_SYMBOL ||
- strcmp("nil", cons->cdr.atom->sym) != 0) {
- fprintf(stream, " . ");
- print_expr_as_sexpr(stream, cons->cdr);
- }
-
- fprintf(stream, ")");
-}
-
-static void print_cons_as_c(FILE *stream, struct Cons *cons)
-{
- trace_assert(stream);
- trace_assert(cons);
-
- fprintf(stream, "CONS(gc, ");
- print_expr_as_c(stream, cons->car);
- fprintf(stream, ", ");
- print_expr_as_c(stream, cons->cdr);
- fprintf(stream, ")");
-}
-
-void print_expr_as_sexpr(FILE *stream, struct Expr expr)
-{
- switch (expr.type) {
- case EXPR_ATOM:
- print_atom_as_sexpr(stream, expr.atom);
- break;
-
- case EXPR_CONS:
- print_cons_as_sexpr(stream, expr.cons);
- break;
-
- case EXPR_VOID:
- break;
- }
-}
-
-void print_expr_as_c(FILE *stream, struct Expr expr)
-{
- trace_assert(stream);
- (void) expr;
-
- switch (expr.type) {
- case EXPR_ATOM:
- print_atom_as_c(stream, expr.atom);
- break;
-
- case EXPR_CONS:
- print_cons_as_c(stream, expr.cons);
- break;
-
- case EXPR_VOID:
- break;
- }
-}
-
-void destroy_expr(struct Expr expr)
-{
- switch (expr.type) {
- case EXPR_ATOM:
- destroy_atom(expr.atom);
- break;
-
- case EXPR_CONS:
- destroy_cons(expr.cons);
- break;
-
- case EXPR_VOID:
- break;
- }
-}
-
-struct Cons *create_cons(Gc *gc, struct Expr car, struct Expr cdr)
-{
- struct Cons *cons = malloc(sizeof(struct Cons));
- if (cons == NULL) {
- return NULL;
- }
-
- cons->car = car;
- cons->cdr = cdr;
-
- if (gc_add_expr(gc, cons_as_expr(cons)) < 0) {
- free(cons);
- return NULL;
- }
-
- return cons;
-}
-
-void destroy_cons(struct Cons *cons)
-{
- free(cons);
-}
-
-struct Atom *create_real_atom(Gc *gc, float real)
-{
- struct Atom *atom = malloc(sizeof(struct Atom));
- if (atom == NULL) {
- return NULL;
- }
- atom->type = ATOM_REAL;
- atom->real = real;
-
- if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
- free(atom);
- return NULL;
- }
-
- return atom;
-}
-
-struct Atom *create_integer_atom(Gc *gc, long int num)
-{
- struct Atom *atom = malloc(sizeof(struct Atom));
- if (atom == NULL) {
- return NULL;
- }
- atom->type = ATOM_INTEGER;
- atom->num = num;
-
- if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
- free(atom);
- return NULL;
- }
-
- return atom;
-}
-
-struct Atom *create_string_atom(Gc *gc, const char *str, const char *str_end)
-{
- struct Atom *atom = malloc(sizeof(struct Atom));
-
- if (atom == NULL) {
- goto error;
- }
-
- atom->type = ATOM_STRING;
- atom->str = string_duplicate(str, str_end);
-
- if (atom->str == NULL) {
- goto error;
- }
-
- if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
- goto error;
- }
-
- return atom;
-
-error:
- if (atom != NULL) {
- if (atom->str != NULL) {
- free(atom->str);
- }
- free(atom);
- }
-
- return NULL;
-}
-
-struct Atom *create_symbol_atom(Gc *gc, const char *sym, const char *sym_end)
-{
- struct Atom *atom = malloc(sizeof(struct Atom));
-
- if (atom == NULL) {
- goto error;
- }
-
- atom->type = ATOM_SYMBOL;
- atom->sym = string_duplicate(sym, sym_end);
-
- if (atom->sym == NULL) {
- goto error;
- }
-
- if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
- goto error;
- }
-
- return atom;
-
-error:
- if (atom != NULL) {
- if (atom->sym != NULL) {
- free(atom->sym);
- }
- free(atom);
- }
-
- return NULL;
-}
-
-struct Atom *create_lambda_atom(Gc *gc, struct Expr args_list, struct Expr body, struct Expr envir)
-{
- struct Atom *atom = malloc(sizeof(struct Atom));
-
- if (atom == NULL) {
- goto error;
- }
-
- atom->type = ATOM_LAMBDA;
- atom->lambda.args_list = args_list;
- atom->lambda.body = body;
- atom->lambda.envir = envir;
-
- if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
- goto error;
- }
-
- return atom;
-
-error:
- if (atom != NULL) {
- free(atom);
- }
-
- return NULL;
-}
-
-struct Atom *create_native_atom(Gc *gc, NativeFunction fun, void *param)
-{
- struct Atom *atom = malloc(sizeof(struct Atom));
-
- if (atom == NULL) {
- goto error;
- }
-
- atom->type = ATOM_NATIVE;
- atom->native.fun = fun;
- atom->native.param = param;
-
- if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
- goto error;
- }
-
- return atom;
-
-error:
- if (atom != NULL) {
- free(atom);
- }
-
- return NULL;
-}
-
-void destroy_atom(struct Atom *atom)
-{
- switch (atom->type) {
- case ATOM_SYMBOL:
- case ATOM_STRING: {
- free(atom->str);
- } break;
-
- case ATOM_LAMBDA:
- case ATOM_NATIVE:
- case ATOM_INTEGER:
- case ATOM_REAL: {
- /* Nothing */
- } break;
- }
-
- free(atom);
-}
-
-static int atom_as_sexpr(struct Atom *atom, char *output, size_t n)
-{
- trace_assert(atom);
- trace_assert(output);
-
- switch (atom->type) {
- case ATOM_SYMBOL: {
- return snprintf(output, n, "%s", atom->sym);
- }
-
- case ATOM_INTEGER: {
- return snprintf(output, n, "%ld", atom->num);
- }
-
- case ATOM_REAL: {
- return snprintf(output, n, "%f", atom->real);
- }
-
- case ATOM_STRING: {
- return snprintf(output, n, "\"%s\"", atom->str);
- }
-
- case ATOM_LAMBDA:
- return snprintf(output, n, "<lambda>");
-
- case ATOM_NATIVE:
- return snprintf(output, n, "<native>");
- }
-
- return 0;
-}
-
-static int cons_as_sexpr(struct Cons *head, char *output, size_t n)
-{
- trace_assert(head);
- trace_assert(output);
-
- /* TODO(#378): cons_as_sexpr does not handle encoding errors of snprintf */
-
- struct Cons *cons = head;
-
- int m = (int) n;
-
- int c = snprintf(output, n, "(");
- if (m - c <= c) {
- return c;
- }
-
- c += expr_as_sexpr(cons->car, output + c, (size_t) (m - c));
- if (m - c <= 0) {
- return c;
- }
-
- while (cons->cdr.type == EXPR_CONS) {
- cons = cons->cdr.cons;
-
- c += snprintf(output + c, (size_t) (m - c), " ");
- if (m - c <= 0) {
- return c;
- }
-
- c += expr_as_sexpr(cons->car, output + c, (size_t) (m - c));
- if (m - c <= 0) {
- return c;
- }
- }
-
- if (cons->cdr.atom->type != ATOM_SYMBOL ||
- strcmp("nil", cons->cdr.atom->sym) != 0) {
-
- c += snprintf(output + c, (size_t) (m - c), " . ");
- if (m - c <= 0) {
- return c;
- }
-
- c += expr_as_sexpr(cons->cdr, output + c, (size_t) (m - c));
- if (m - c <= 0) {
- return c;
- }
- }
-
- c += snprintf(output + c, (size_t) (m - c), ")");
- if (m - c <= 0) {
- return c;
- }
-
- return c;
-}
-
-int expr_as_sexpr(struct Expr expr, char *output, size_t n)
-{
- switch(expr.type) {
- case EXPR_ATOM:
- return atom_as_sexpr(expr.atom, output, n);
-
- case EXPR_CONS:
- return cons_as_sexpr(expr.cons, output, n);
-
- case EXPR_VOID:
- return 0;
- }
-
- return 0;
-}
-
-const char *expr_type_as_string(enum ExprType expr_type)
-{
- switch (expr_type) {
- case EXPR_ATOM: return "EXPR_ATOM";
- case EXPR_CONS: return "EXPR_CONS";
- case EXPR_VOID: return "EXPR_VOID";
- }
-
- return "";
-}
-
-const char *atom_type_as_string(enum AtomType atom_type)
-{
- switch (atom_type) {
- case ATOM_SYMBOL: return "ATOM_SYMBOL";
- case ATOM_INTEGER: return "ATOM_INTEGER";
- case ATOM_REAL: return "ATOM_REAL";
- case ATOM_STRING: return "ATOM_STRING";
- case ATOM_LAMBDA: return "ATOM_LAMBDA";
- case ATOM_NATIVE: return "ATOM_NATIVE";
- }
-
- return "";
-}
+++ /dev/null
-#ifndef EXPR_H_
-#define EXPR_H_
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-typedef struct Gc Gc;
-typedef struct Scope Scope;
-
-struct Cons;
-struct Atom;
-
-#define INTEGER(G, X) atom_as_expr(create_integer_atom(G, X))
-#define REAL(G, X) atom_as_expr(create_real_atom(G, X))
-#define STRING(G, S) atom_as_expr(create_string_atom(G, S, NULL))
-#define SYMBOL(G, S) atom_as_expr(create_symbol_atom(G, S, NULL))
-#define NATIVE(G, F, P) atom_as_expr(create_native_atom(G, F, P))
-#define CONS(G, CAR, CDR) cons_as_expr(create_cons(G, CAR, CDR))
-#define NIL(G) SYMBOL(G, "nil")
-#define T(G) SYMBOL(G, "t")
-
-#define CAR(O) ((O).cons->car)
-#define CDR(O) ((O).cons->cdr)
-
-enum ExprType
-{
- EXPR_ATOM = 0,
- EXPR_CONS,
- EXPR_VOID
-};
-
-struct Expr
-{
- enum ExprType type;
- union {
- struct Cons *cons;
- struct Atom *atom;
- };
-};
-
-// Prototype to prevent https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113
-const char *expr_type_as_string(enum ExprType expr_type);
-
-struct Expr atom_as_expr(struct Atom *atom);
-struct Expr cons_as_expr(struct Cons *cons);
-struct Expr void_expr(void);
-
-void destroy_expr(struct Expr expr);
-void print_expr_as_sexpr(FILE *stream, struct Expr expr);
-void print_expr_as_c(FILE *stream, struct Expr expr);
-int expr_as_sexpr(struct Expr expr, char *output, size_t n);
-
-// TODO(#337): EvalResult does not belong to expr unit
-struct EvalResult
-{
- bool is_error;
- struct Expr expr;
-};
-
-
-typedef struct EvalResult (*NativeFunction)(void *param, Gc *gc, struct Scope *scope, struct Expr args);
-
-struct Native
-{
- NativeFunction fun;
- void *param;
-};
-
-struct Lambda
-{
- struct Expr args_list;
- struct Expr body;
- struct Expr envir;
-};
-
-enum AtomType
-{
- ATOM_SYMBOL = 0,
- ATOM_INTEGER,
- ATOM_REAL,
- ATOM_STRING,
- ATOM_LAMBDA,
- ATOM_NATIVE
-};
-
-const char *atom_type_as_string(enum AtomType atom_type);
-
-struct Atom
-{
- enum AtomType type;
- union
- {
- // TODO(#330): Atom doesn't support floats
- long int num; // ATOM_INTEGER
- float real; // ATOM_REAL
- char *sym; // ATOM_SYMBOL
- char *str; // ATOM_STRING
- struct Lambda lambda; // ATOM_LAMBDA
- struct Native native; // ATOM_NATIVE
- };
-};
-
-struct Atom *create_integer_atom(Gc *gc, long int num);
-struct Atom *create_real_atom(Gc *gc, float num);
-struct Atom *create_string_atom(Gc *gc, const char *str, const char *str_end);
-struct Atom *create_symbol_atom(Gc *gc, const char *sym, const char *sym_end);
-struct Atom *create_lambda_atom(Gc *gc, struct Expr args_list, struct Expr body, struct Expr envir);
-struct Atom *create_native_atom(Gc *gc, NativeFunction fun, void *param);
-void destroy_atom(struct Atom *atom);
-void print_atom_as_sexpr(FILE *stream, struct Atom *atom);
-
-struct Cons
-{
- struct Expr car;
- struct Expr cdr;
-};
-
-struct Cons *create_cons(Gc *gc, struct Expr car, struct Expr cdr);
-void destroy_cons(struct Cons *cons);
-void print_cons_as_sexpr(FILE *stream, struct Cons *cons);
-
-#endif // EXPR_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "builtins.h"
-#include "expr.h"
-#include "gc.h"
-#include "system/lt.h"
-
-#define GC_INITIAL_CAPACITY 256
-
-struct Gc
-{
- Lt *lt;
- struct Expr *exprs;
- int *visited;
- size_t size;
- size_t capacity;
-};
-
-static intptr_t value_of_expr(struct Expr expr)
-{
- if (expr.type == EXPR_CONS) {
- return (intptr_t) expr.cons;
- } else if (expr.type == EXPR_ATOM) {
- return (intptr_t) expr.atom;
- } else {
- return 0;
- }
-}
-
-static int compare_exprs(const void *a, const void *b)
-{
- trace_assert(a);
- trace_assert(b);
-
- const intptr_t ptr_a = value_of_expr(*(const struct Expr *)a);
- const intptr_t ptr_b = value_of_expr(*(const struct Expr *)b);
- const intptr_t d = ptr_b - ptr_a;
-
- if (d < 0) {
- return -1;
- } else if (d > 0) {
- return 1;
- } else {
- return 0;
- }
-}
-
-Gc *create_gc(void)
-{
- Lt *lt = create_lt();
-
- Gc *gc = PUSH_LT(lt, calloc(1, sizeof(Gc)), free);
- if (gc == NULL) {
- RETURN_LT(lt, NULL);
- }
- gc->lt = lt;
-
- gc->exprs = PUSH_LT(lt, calloc(GC_INITIAL_CAPACITY, sizeof(struct Expr)), free);
- if (gc->exprs == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- gc->visited = PUSH_LT(lt, calloc(GC_INITIAL_CAPACITY, sizeof(int)), free);
- if (gc->visited == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- gc->size = 0;
- gc->capacity = GC_INITIAL_CAPACITY;
-
- return gc;
-}
-
-void destroy_gc(Gc *gc)
-{
- trace_assert(gc);
-
- for (size_t i = 0; i < gc->size; ++i) {
- destroy_expr(gc->exprs[i]);
- }
-
- RETURN_LT0(gc->lt);
-}
-
-int gc_add_expr(Gc *gc, struct Expr expr)
-{
- trace_assert(gc);
-
- if (gc->size >= gc->capacity) {
- const size_t new_capacity = gc->capacity * 2;
- struct Expr *const new_exprs = realloc(
- gc->exprs,
- sizeof(struct Expr) * new_capacity);
-
- if (new_exprs == NULL) {
- return -1;
- }
-
- int *const new_visited = realloc(
- gc->visited,
- sizeof(int) * new_capacity);
-
- if (new_visited == NULL) {
- return -1;
- }
-
- gc->capacity = new_capacity;
- gc->exprs = REPLACE_LT(gc->lt, gc->exprs, new_exprs);
- gc->visited = REPLACE_LT(gc->lt, gc->visited, new_visited);
- }
-
- gc->exprs[gc->size++] = expr;
-
- return 0;
-}
-
-static long int gc_find_expr(Gc *gc, struct Expr expr)
-{
- trace_assert(gc);
- (void) expr;
-
- struct Expr *result =
- (struct Expr *) bsearch(&expr, gc->exprs, gc->size,
- sizeof(struct Expr), compare_exprs);
-
- if (result == NULL) {
- return -1;
- }
-
- return (long int) (result - gc->exprs);
-}
-
-static void gc_traverse_expr(Gc *gc, struct Expr root)
-{
- trace_assert(gc);
- trace_assert(root.type != EXPR_VOID);
- const long int root_index = gc_find_expr(gc, root);
- if (root_index < 0) {
- fprintf(stderr, "GC tried to collect something that was not registered\n");
- print_expr_as_sexpr(stderr, root);
- fprintf(stderr, "\n");
- trace_assert(root_index >= 0);
- }
-
- if (gc->visited[root_index]) {
- return;
- }
-
- gc->visited[root_index] = 1;
-
- if (cons_p(root)) {
- gc_traverse_expr(gc, root.cons->car);
- gc_traverse_expr(gc, root.cons->cdr);
- } else if (root.type == EXPR_ATOM
- && root.atom->type == ATOM_LAMBDA) {
- gc_traverse_expr(gc, root.atom->lambda.args_list);
- gc_traverse_expr(gc, root.atom->lambda.body);
- gc_traverse_expr(gc, root.atom->lambda.envir);
- }
-}
-
-void gc_collect(Gc *gc, struct Expr root)
-{
- trace_assert(gc);
- (void) root;
-
- /* Sort gc->exprs O(nlogn) */
- qsort(gc->exprs, gc->size, sizeof(struct Expr), compare_exprs);
-
- /* Defragment O(n) */
- while(gc->size > 0 && gc->exprs[gc->size - 1].type == EXPR_VOID) {
- gc->size--;
- }
-
- /* Initialize visited array O(n) */
- memset(gc->visited, 0, sizeof(int) * gc->size);
-
- /* Traverse root O(nlogn) */
- gc_traverse_expr(gc, root);
-
- /* Dealloc unvisted O(n) */
- for (size_t i = 0; i < gc->size; ++i) {
- if (!gc->visited[i]) {
- destroy_expr(gc->exprs[i]);
- gc->exprs[i] = void_expr();
- }
- }
-}
-
-void gc_inspect(const Gc *gc)
-{
- for (size_t i = 0; i < gc->size; ++i) {
- if (gc->exprs[i].type == EXPR_VOID) {
- printf(".");
- } else {
- printf("+");
- }
- }
- printf("\n");
-}
+++ /dev/null
-#ifndef GC_H_
-#define GC_H_
-
-#include "expr.h"
-
-typedef struct Gc Gc;
-
-Gc *create_gc(void);
-void destroy_gc(Gc *gc);
-
-int gc_add_expr(Gc *gc, struct Expr expr);
-void gc_collect(Gc *gc, struct Expr root);
-void gc_inspect(const Gc *gc);
-
-#endif // GC_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include <math.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdbool.h>
-
-#include "./builtins.h"
-#include "./expr.h"
-#include "./interpreter.h"
-#include "./scope.h"
-
-struct EvalResult eval_success(struct Expr expr)
-{
- struct EvalResult result = {
- .is_error = false,
- .expr = expr,
- };
-
- return result;
-}
-
-struct EvalResult eval_failure(struct Expr error)
-{
- struct EvalResult result = {
- .is_error = true,
- .expr = error,
- };
-
- return result;
-}
-
-struct EvalResult
-wrong_argument_type(Gc *gc, const char *type, struct Expr obj)
-{
- return eval_failure(
- list(gc, "qqe", "wrong-argument-type", type, obj));
-}
-
-struct EvalResult
-wrong_integer_of_arguments(Gc *gc, long int count)
-{
- return eval_failure(
- CONS(gc,
- SYMBOL(gc, "wrong-integer-of-arguments"),
- INTEGER(gc, count)));
-}
-
-struct EvalResult
-not_implemented(Gc *gc)
-{
- return eval_failure(SYMBOL(gc, "not-implemented"));
-}
-
-struct EvalResult
-read_error(Gc *gc, const char *error_message, long int character)
-{
- return eval_failure(
- list(gc, "qsd", "read-error", error_message, character));
-}
-
-static struct EvalResult eval_atom(Gc *gc, struct Scope *scope, struct Atom *atom)
-{
- (void) scope;
- (void) gc;
-
- switch (atom->type) {
- case ATOM_INTEGER:
- case ATOM_REAL:
- case ATOM_STRING:
- case ATOM_LAMBDA:
- case ATOM_NATIVE: {
- return eval_success(atom_as_expr(atom));
- }
-
- case ATOM_SYMBOL: {
- struct Expr value = get_scope_value(scope, atom_as_expr(atom));
-
- if (nil_p(value)) {
- return eval_failure(CONS(gc,
- SYMBOL(gc, "void-variable"),
- atom_as_expr(atom)));
- }
-
- return eval_success(value.cons->cdr);
- }
- }
-
- return eval_failure(CONS(gc,
- SYMBOL(gc, "unexpected-expression"),
- atom_as_expr(atom)));
-}
-
-static struct EvalResult eval_all_args(Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) scope;
- (void) args;
-
- switch(args.type) {
- case EXPR_ATOM:
- return eval_atom(gc, scope, args.atom);
-
- case EXPR_CONS: {
- struct EvalResult car = eval(gc, scope, args.cons->car);
- if (car.is_error) {
- return car;
- }
-
- struct EvalResult cdr = eval_all_args(gc, scope, args.cons->cdr);
- if (cdr.is_error) {
- return cdr;
- }
-
- return eval_success(cons_as_expr(create_cons(gc, car.expr, cdr.expr)));
- }
-
- default: {}
- }
-
- return eval_failure(CONS(gc,
- SYMBOL(gc, "unexpected-expression"),
- args));
-}
-
-static struct EvalResult call_lambda(Gc *gc,
- struct Expr lambda,
- struct Expr args) {
- if (!lambda_p(lambda)) {
- return eval_failure(CONS(gc,
- SYMBOL(gc, "expected-callable"),
- lambda));
- }
-
- if (!list_p(args)) {
- return eval_failure(CONS(gc,
- SYMBOL(gc, "expected-list"),
- args));
- }
-
- struct Expr vars = lambda.atom->lambda.args_list;
-
- if (length_of_list(args) != length_of_list(vars)) {
- return eval_failure(CONS(gc,
- SYMBOL(gc, "wrong-integer-of-arguments"),
- INTEGER(gc, length_of_list(args))));
- }
-
- struct Scope scope = {
- .expr = lambda.atom->lambda.envir
- };
- push_scope_frame(gc, &scope, vars, args);
-
- struct Expr body = lambda.atom->lambda.body;
-
- struct EvalResult result = eval_success(NIL(gc));
-
- while (!nil_p(body)) {
- result = eval(gc, &scope, body.cons->car);
- if (result.is_error) {
- return result;
- }
- body = body.cons->cdr;
- }
-
- return result;
-}
-
-static struct EvalResult eval_funcall(Gc *gc,
- struct Scope *scope,
- struct Expr callable_expr,
- struct Expr args_expr) {
- struct EvalResult callable_result = eval(gc, scope, callable_expr);
- if (callable_result.is_error) {
- return callable_result;
- }
-
- struct EvalResult args_result = symbol_p(callable_expr) && is_special(callable_expr.atom->sym)
- ? eval_success(args_expr)
- : eval_all_args(gc, scope, args_expr);
-
- if (args_result.is_error) {
- return args_result;
- }
-
- if (callable_result.expr.type == EXPR_ATOM &&
- callable_result.expr.atom->type == ATOM_NATIVE) {
- return ((NativeFunction)callable_result.expr.atom->native.fun)(
- callable_result.expr.atom->native.param, gc, scope, args_result.expr);
- }
-
- return call_lambda(gc, callable_result.expr, args_result.expr);
-}
-
-
-struct EvalResult eval_block(Gc *gc, struct Scope *scope, struct Expr block)
-{
- trace_assert(gc);
- trace_assert(scope);
-
- if (!list_p(block)) {
- return wrong_argument_type(gc, "listp", block);
- }
-
- struct Expr head = block;
- struct EvalResult eval_result = eval_success(NIL(gc));
-
- while (cons_p(head)) {
- eval_result = eval(gc, scope, CAR(head));
- if (eval_result.is_error) {
- return eval_result;
- }
-
- head = CDR(head);
- }
-
- return eval_result;
-}
-
-struct EvalResult eval(Gc *gc, struct Scope *scope, struct Expr expr)
-{
- switch(expr.type) {
- case EXPR_ATOM:
- return eval_atom(gc, scope, expr.atom);
-
- case EXPR_CONS:
- return eval_funcall(gc, scope, expr.cons->car, expr.cons->cdr);
-
- default: {}
- }
-
- return eval_failure(CONS(gc,
- SYMBOL(gc, "unexpected-expression"),
- expr));
-}
-
-struct EvalResult
-car(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr xs = NIL(gc);
-
- struct EvalResult result = match_list(gc, "e", args, &xs);
- if (result.is_error) {
- return result;
- }
-
- if (nil_p(xs)) {
- return eval_success(xs);
- }
-
- if (!cons_p(xs)) {
- return wrong_argument_type(gc, "consp", xs);
- }
-
- return eval_success(CAR(xs));
-}
-
-struct EvalResult
-match_list(struct Gc *gc, const char *format, struct Expr xs, ...)
-{
- va_list args_list;
- va_start(args_list, xs);
-
- // TODO(#1098): match_list does not support real numbers
-
- long int i = 0;
- for (i = 0; *format != 0 && !nil_p(xs); ++i) {
- if (!cons_p(xs)) {
- va_end(args_list);
- return wrong_argument_type(gc, "consp", xs);
- }
-
- struct Expr x = CAR(xs);
-
- switch (*format) {
- case 'd': {
- if (!integer_p(x)) {
- va_end(args_list);
- return wrong_argument_type(gc, "integerp", x);
- }
-
- long int *p = va_arg(args_list, long int *);
- if (p != NULL) {
- *p = x.atom->num;
- }
- } break;
-
- case 's': {
- if (!string_p(x)) {
- va_end(args_list);
- return wrong_argument_type(gc, "stringp", x);
- }
-
- const char **p = va_arg(args_list, const char**);
- if (p != NULL) {
- *p = x.atom->str;
- }
- } break;
-
- case 'q': {
- if (!symbol_p(x)) {
- va_end(args_list);
- return wrong_argument_type(gc, "symbolp", x);
- }
-
- const char **p = va_arg(args_list, const char**);
- if (p != NULL) {
- *p = x.atom->sym;
- }
- } break;
-
- case 'e': {
- struct Expr *p = va_arg(args_list, struct Expr*);
- *p = x;
- } break;
-
- case '*': {
- struct Expr *p = va_arg(args_list, struct Expr*);
- if (p != NULL) {
- *p = xs;
- }
- xs = NIL(gc);
- } break;
- }
-
- format++;
- if (!nil_p(xs)) {
- xs = CDR(xs);
- }
- }
-
- if (*format == '*' && nil_p(xs)) {
- struct Expr *p = va_arg(args_list, struct Expr*);
- if (p != NULL) {
- *p = NIL(gc);
- }
- format++;
- }
-
- if (*format != 0 || !nil_p(xs)) {
- va_end(args_list);
- return wrong_integer_of_arguments(gc, i);
- }
-
- va_end(args_list);
- return eval_success(NIL(gc));
-}
+++ /dev/null
-#ifndef INTERPRETER_H_
-#define INTERPRETER_H_
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "expr.h"
-
-struct Scope;
-struct Gc;
-
-
-struct EvalResult eval_success(struct Expr expr);
-struct EvalResult eval_failure(struct Expr expr);
-struct EvalResult
-wrong_argument_type(Gc *gc, const char *type, struct Expr obj);
-struct EvalResult
-wrong_integer_of_arguments(Gc *gc, long int count);
-struct EvalResult
-not_implemented(Gc *gc);
-struct EvalResult
-read_error(Gc *gc, const char *error_message, long int character);
-
-struct EvalResult
-car(void *param, Gc *gc, struct Scope *scope, struct Expr args);
-
-struct EvalResult eval(Gc *gc, struct Scope *scope, struct Expr expr);
-struct EvalResult eval_block(Gc *gc, struct Scope *scope, struct Expr block);
-
-struct EvalResult
-match_list(struct Gc *gc, const char *format, struct Expr args, ...);
-
-#endif // INTERPRETER_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include <ctype.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-#include "ebisp/builtins.h"
-#include "ebisp/parser.h"
-#include "system/lt.h"
-#include "system/lt_adapters.h"
-
-#define MAX_BUFFER_LENGTH (5 * 1000 * 1000)
-
-static struct ParseResult parse_expr(Gc *gc, struct Token current_token);
-
-static struct ParseResult parse_cdr(Gc *gc, struct Token current_token)
-{
- if (*current_token.begin != '.') {
- return parse_failure("Expected .", current_token.begin);
- }
-
- struct ParseResult cdr = read_expr_from_string(gc, current_token.end);
- if (cdr.is_error) {
- return cdr;
- }
-
- current_token = next_token(cdr.end);
-
- if (*current_token.begin != ')') {
- return parse_failure("Expected )", current_token.begin);
- }
-
- return parse_success(cdr.expr, current_token.end);
-}
-
-static struct ParseResult parse_list_end(Gc *gc, struct Token current_token)
-{
- if (*current_token.begin != ')') {
- return parse_failure("Expected )", current_token.begin);
- }
-
- return parse_success(atom_as_expr(create_symbol_atom(gc, "nil", NULL)),
- current_token.end);
-}
-
-static struct ParseResult parse_list(Gc *gc, struct Token current_token)
-{
- if (*current_token.begin != '(') {
- return parse_failure("Expected (", current_token.begin);
- }
-
- current_token = next_token(current_token.end);
-
- if (*current_token.begin == ')') {
- return parse_list_end(gc, current_token);
- }
-
- struct ParseResult car = parse_expr(gc, current_token);
- if (car.is_error) {
- return car;
- }
-
- struct Cons *list = create_cons(gc, car.expr, void_expr());
- struct Cons *cons = list;
- current_token = next_token(car.end);
-
- while (*current_token.begin != '.' &&
- *current_token.begin != ')' &&
- *current_token.begin != 0) {
- car = parse_expr(gc, current_token);
- if (car.is_error) {
- return car;
- }
-
- cons->cdr = cons_as_expr(create_cons(gc, car.expr, void_expr()));
- cons = cons->cdr.cons;
-
- current_token = next_token(car.end);
- }
-
- struct ParseResult cdr = *current_token.begin == '.'
- ? parse_cdr(gc, current_token)
- : parse_list_end(gc, current_token);
-
- if (cdr.is_error) {
- return cdr;
- }
-
- cons->cdr = cdr.expr;
-
- return parse_success(cons_as_expr(list), cdr.end);
-}
-
-static struct ParseResult parse_string(Gc *gc, struct Token current_token)
-{
- if (*current_token.begin != '"') {
- return parse_failure("Expected \"", current_token.begin);
- }
-
- if (*(current_token.end - 1) != '"') {
- return parse_failure("Unclosed string", current_token.begin);
- }
-
- if (current_token.begin + 1 == current_token.end) {
- return parse_success(atom_as_expr(create_string_atom(gc, "", NULL)),
- current_token.end);
- }
-
- return parse_success(
- atom_as_expr(
- create_string_atom(gc, current_token.begin + 1, current_token.end - 1)),
- current_token.end);
-}
-
-static struct ParseResult parse_integer(Gc *gc, struct Token current_token)
-{
- char *endptr = 0;
- const long int x = strtol(current_token.begin, &endptr, 10);
-
- if ((current_token.begin == endptr) || (current_token.end != endptr)) {
- return parse_failure("Expected integer", current_token.begin);
- }
-
- return parse_success(
- atom_as_expr(create_integer_atom(gc, x)),
- current_token.end);
-}
-
-static struct ParseResult parse_real(Gc *gc, struct Token current_token)
-{
- trace_assert(gc);
-
- char *endptr = 0;
- const float x = strtof(current_token.begin, &endptr);
-
- if ((current_token.begin == endptr) || (current_token.end != endptr)) {
- return parse_failure("Expected real", current_token.begin);
- }
-
- return parse_success(REAL(gc, x), current_token.end);
-}
-
-static struct ParseResult parse_symbol(Gc *gc, struct Token current_token)
-{
- if (*current_token.begin == 0) {
- return parse_failure("EOF", current_token.begin);
- }
-
- return parse_success(
- atom_as_expr(create_symbol_atom(gc, current_token.begin, current_token.end)),
- current_token.end);
-}
-
-static struct ParseResult parse_expr(Gc *gc, struct Token current_token)
-{
- if (*current_token.begin == 0) {
- return parse_failure("EOF", current_token.begin);
- }
-
- switch (*current_token.begin) {
- case '(': return parse_list(gc, current_token);
- /* TODO(#292): parser does not support escaped string characters */
- case '"': return parse_string(gc, current_token);
- case '\'': {
- struct ParseResult result = parse_expr(gc, next_token(current_token.end));
-
- if (result.is_error) {
- return result;
- }
-
- result.expr = list(gc, "qe", "quote", result.expr);
-
- return result;
- } break;
-
- case '`': {
- struct ParseResult result = parse_expr(gc, next_token(current_token.end));
-
- if (result.is_error) {
- return result;
- }
-
- result.expr = list(gc, "qe", "quasiquote", result.expr);
-
- return result;
- } break;
-
- case ',': {
- struct ParseResult result = parse_expr(gc, next_token(current_token.end));
-
- if (result.is_error) {
- return result;
- }
-
- result.expr = list(gc, "qe", "unquote", result.expr);
-
- return result;
- } break;
-
- default: {}
- }
-
- if (*current_token.begin == '-' || isdigit(*current_token.begin)) {
- struct ParseResult result;
-
- result = parse_integer(gc, current_token); if (!result.is_error) return result;
- result = parse_real(gc, current_token); if (!result.is_error) return result;
- }
-
- return parse_symbol(gc, current_token);
-}
-
-struct ParseResult read_expr_from_string(Gc *gc, const char *str)
-{
- trace_assert(gc);
- trace_assert(str);
- return parse_expr(gc, next_token(str));
-}
-
-struct ParseResult read_all_exprs_from_string(Gc *gc, const char *str)
-{
- trace_assert(gc);
- trace_assert(str);
-
- struct Token current_token = next_token(str);
- if (*current_token.end == 0) {
- return parse_success(NIL(gc), current_token.end);
- }
-
- struct ParseResult parse_result = parse_expr(gc, current_token);
- if (parse_result.is_error) {
- return parse_result;
- }
-
- struct Cons *head = create_cons(gc, parse_result.expr, void_expr());
- struct Cons *cons = head;
-
- current_token = next_token(parse_result.end);
- while (*current_token.end != 0) {
- parse_result = parse_expr(gc, current_token);
- if (parse_result.is_error) {
- return parse_result;
- }
-
- cons->cdr = CONS(gc, parse_result.expr, void_expr());
- cons = cons->cdr.cons;
- current_token = next_token(parse_result.end);
- }
-
- cons->cdr = NIL(gc);
-
- return parse_success(cons_as_expr(head), parse_result.end);
-}
-
-struct ParseResult read_expr_from_file(Gc *gc, const char *filename)
-{
- trace_assert(filename);
-
- Lt *lt = create_lt();
-
- FILE *stream = PUSH_LT(lt, fopen(filename, "rb"), fclose_lt);
- if (!stream) {
- /* TODO(#307): ParseResult should not be used for reporting IO failures */
- RETURN_LT(lt, parse_failure(strerror(errno), NULL));
- }
-
- if (fseek(stream, 0, SEEK_END) != 0) {
- RETURN_LT(lt, parse_failure("Could not find the end of the file", NULL));
- }
-
- const long int buffer_length = ftell(stream);
-
- if (buffer_length < 0) {
- RETURN_LT(lt, parse_failure("Couldn't get the size of file", NULL));
- }
-
- if (buffer_length == 0) {
- RETURN_LT(lt, parse_failure("File is empty", NULL));
- }
-
- if (buffer_length >= MAX_BUFFER_LENGTH) {
- RETURN_LT(lt, parse_failure("File is too big", NULL));
- }
-
- if (fseek(stream, 0, SEEK_SET) != 0) {
- RETURN_LT(lt, parse_failure("Could not find the beginning of the file", NULL));
- }
-
- char * const buffer = PUSH_LT(lt, malloc((size_t) buffer_length + 1), free);
- if (buffer == NULL) {
- RETURN_LT(lt, parse_failure(strerror(errno), NULL));
- }
-
- if (fread(buffer, 1, (size_t) buffer_length, stream) != (size_t) buffer_length) {
- RETURN_LT(lt, parse_failure("Could not read the file", NULL));
- }
-
- struct ParseResult result = read_expr_from_string(gc, buffer);
-
- RETURN_LT(lt, result);
-}
-
-/* TODO(#598): duplicate code in read_all_exprs_from_file and read_expr_from_file */
-struct ParseResult read_all_exprs_from_file(Gc *gc, const char *filename)
-{
- trace_assert(filename);
-
- Lt *lt = create_lt();
-
- FILE *stream = PUSH_LT(lt, fopen(filename, "rb"), fclose_lt);
- if (!stream) {
- RETURN_LT(lt, parse_failure(strerror(errno), NULL));
- }
-
- if (fseek(stream, 0, SEEK_END) != 0) {
- RETURN_LT(lt, parse_failure("Could not find the end of the file", NULL));
- }
-
- const long int buffer_length = ftell(stream);
-
- if (buffer_length < 0) {
- RETURN_LT(lt, parse_failure("Couldn't get the size of file", NULL));
- }
-
- if (buffer_length == 0) {
- RETURN_LT(lt, parse_failure("File is empty", NULL));
- }
-
- if (buffer_length >= MAX_BUFFER_LENGTH) {
- RETURN_LT(lt, parse_failure("File is too big", NULL));
- }
-
- if (fseek(stream, 0, SEEK_SET) != 0) {
- RETURN_LT(lt, parse_failure("Could not find the beginning of the file", NULL));
- }
-
- char * const buffer = PUSH_LT(lt, malloc((size_t) buffer_length + 1), free);
- if (buffer == NULL) {
- RETURN_LT(lt, parse_failure(strerror(errno), NULL));
- }
-
- if (fread(buffer, 1, (size_t) buffer_length, stream) != (size_t) buffer_length) {
- RETURN_LT(lt, parse_failure("Could not read the file", NULL));
- }
-
- struct ParseResult result = read_all_exprs_from_string(gc, buffer);
-
- RETURN_LT(lt, result);
-}
-
-struct ParseResult parse_success(struct Expr expr,
- const char *end)
-{
- struct ParseResult result = {
- .is_error = false,
- .expr = expr,
- .end = end
- };
-
- return result;
-}
-
-struct ParseResult parse_failure(const char *error_message,
- const char *end)
-{
- struct ParseResult result = {
- .is_error = true,
- .error_message = error_message,
- .end = end
- };
-
- return result;
-}
-
-void print_parse_error(FILE *stream,
- const char *str,
- struct ParseResult result)
-{
- /* TODO(#294): print_parse_error doesn't support multiple lines */
- if (!result.is_error) {
- return;
- }
-
- if (result.end) {
- fprintf(stream, "%s\n", str);
- for (size_t i = 0; i < (size_t) (result.end - str); ++i) {
- fprintf(stream, " ");
- }
- fprintf(stream, "^\n");
- }
-
- fprintf(stream, "%s\n", result.error_message);
-}
+++ /dev/null
-#ifndef PARSER_H_
-#define PARSER_H_
-
-#include <stdio.h>
-#include <stdbool.h>
-#include "ebisp/expr.h"
-#include "ebisp/tokenizer.h"
-
-struct ParseResult
-{
- bool is_error;
- const char *end;
- union {
- struct Expr expr;
- const char *error_message;
- };
-};
-
-struct ParseResult parse_success(struct Expr expr,
- const char *end);
-struct ParseResult parse_failure(const char *error,
- const char *end);
-
-
-struct ParseResult read_expr_from_string(Gc *gc, const char *str);
-struct ParseResult read_all_exprs_from_string(Gc *gc, const char *str);
-
-struct ParseResult read_expr_from_file(Gc *gc, const char *filename);
-struct ParseResult read_all_exprs_from_file(Gc *gc, const char *filename);
-
-void print_parse_error(FILE *stream,
- const char *str,
- struct ParseResult result);
-// TODO(#668): there is no way to print parse error after parsing a file
-
-#endif // PARSER_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include <stdbool.h>
-
-#include "gc.h"
-#include "interpreter.h"
-#include "parser.h"
-#include "repl_runtime.h"
-#include "scope.h"
-#include "std.h"
-
-#define REPL_BUFFER_MAX 1024
-
-static void eval_line(Gc *gc, Scope *scope, const char *line)
-{
- /* TODO(#465): eval_line could be implemented with read_all_exprs_from_string */
- while (*line != 0) {
- gc_collect(gc, scope->expr);
-
- struct ParseResult parse_result = read_expr_from_string(gc, line);
- if (parse_result.is_error) {
- print_parse_error(stderr, line, parse_result);
- return;
- }
-
- struct EvalResult eval_result = eval(gc, scope, parse_result.expr);
- if (eval_result.is_error) {
- fprintf(stderr, "Error:\t");
- print_expr_as_sexpr(stderr, eval_result.expr);
- fprintf(stderr, "\n");
- return;
- }
-
- print_expr_as_sexpr(stderr, eval_result.expr);
- fprintf(stdout, "\n");
-
- line = next_token(parse_result.end).begin;
- }
-}
-
-int main(int argc, char *argv[])
-{
- (void) argc;
- (void) argv;
-
- char buffer[REPL_BUFFER_MAX + 1];
-
- Gc *gc = create_gc();
- struct Scope scope = create_scope(gc);
-
- load_std_library(gc, &scope);
- load_repl_runtime(gc, &scope);
-
- while (true) {
- printf("> ");
-
- if (fgets(buffer, REPL_BUFFER_MAX, stdin) == NULL) {
- return -1;
- }
-
- eval_line(gc, &scope, buffer);
- }
-
- destroy_gc(gc);
-
- return 0;
-}
+++ /dev/null
-#include "system/stacktrace.h"
-
-#include "scope.h"
-#include "interpreter.h"
-#include "gc.h"
-#include "expr.h"
-#include "repl_runtime.h"
-
-static struct EvalResult gc_inspect_adapter(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) param;
- (void) args;
-
- gc_inspect(gc);
-
- return eval_success(NIL(gc));
-}
-
-static struct EvalResult quit(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) args;
- (void) param;
-
- exit(0);
-
- return eval_success(NIL(gc));
-}
-
-static struct EvalResult get_scope(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) param;
- (void) args;
-
- return eval_success(scope->expr);
-}
-
-static struct EvalResult print(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) param;
-
- const char *s = NULL;
- struct EvalResult result = match_list(gc, "s", args, &s);
- if (result.is_error) {
- return result;
- }
-
- printf("%s\n", s);
-
- return eval_success(NIL(gc));
-}
-
-void load_repl_runtime(Gc *gc, struct Scope *scope)
-{
- set_scope_value(gc, scope, SYMBOL(gc, "quit"), NATIVE(gc, quit, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "gc-inspect"), NATIVE(gc, gc_inspect_adapter, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "scope"), NATIVE(gc, get_scope, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "print"), NATIVE(gc, print, NULL));
-}
+++ /dev/null
-#ifndef REPL_RUNTIME_H_
-#define REPL_RUNTIME_H_
-
-typedef struct Gc Gc;
-struct Scope;
-
-void load_repl_runtime(Gc *gc, struct Scope *scope);
-
-#endif // REPL_RUNTIME_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include "./scope.h"
-
-static struct Expr get_scope_value_impl(struct Expr scope, struct Expr name)
-{
- if (cons_p(scope)) {
- struct Expr value = assoc(name, scope.cons->car);
- return nil_p(value) ? get_scope_value_impl(scope.cons->cdr, name) : value;
- }
-
- return scope;
-}
-
-struct Expr get_scope_value(const struct Scope *scope, struct Expr name)
-{
- return get_scope_value_impl(scope->expr, name);
-}
-
-static struct Expr set_scope_value_impl(Gc *gc, struct Expr scope, struct Expr name, struct Expr value)
-{
- if (cons_p(scope)) {
- struct Expr value_cell = assoc(name, scope.cons->car);
-
- if (!nil_p(value_cell)) {
- /* A binding already exists, mutate it */
- value_cell.cons->cdr = value;
-
- return scope;
- } else if (nil_p(scope.cons->cdr)) {
- /* We're at the global scope, add a binding, preserving
- * the identity of the environment list "spine" so that
- * closed-over environments see the new value cell */
- scope.cons->car = CONS(gc, CONS(gc, name, value), scope.cons->car);
-
- return scope;
- } else {
- /* We haven't found a value cell yet, and we're not at
- * global scope, so recurse */
- set_scope_value_impl(gc, scope.cons->cdr, name, value);
-
- return scope;
- }
- } else {
- /* ??? Should never happen? */
- return CONS(gc,
- CONS(gc, CONS(gc, name, value), NIL(gc)),
- scope);
- }
-}
-
-struct Scope create_scope(Gc *gc)
-{
- struct Scope scope = {
- .expr = CONS(gc, NIL(gc), NIL(gc))
- };
- return scope;
-}
-
-void set_scope_value(Gc *gc, struct Scope *scope, struct Expr name, struct Expr value)
-{
- scope->expr = set_scope_value_impl(gc, scope->expr, name, value);
-}
-
-void push_scope_frame(Gc *gc, struct Scope *scope, struct Expr vars, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr frame = NIL(gc);
-
- while(!nil_p(vars) && !nil_p(args)) {
- frame = CONS(gc,
- CONS(gc, vars.cons->car, args.cons->car),
- frame);
- vars = vars.cons->cdr;
- args = args.cons->cdr;
- }
-
- scope->expr = CONS(gc, frame, scope->expr);
-}
-
-void pop_scope_frame(Gc *gc, struct Scope *scope)
-{
- trace_assert(gc);
- trace_assert(scope);
-
- if (!nil_p(scope->expr)) {
- scope->expr = scope->expr.cons->cdr;
- }
-}
+++ /dev/null
-#ifndef SCOPE_H_
-#define SCOPE_H_
-
-#include "expr.h"
-#include "builtins.h"
-
-struct Scope
-{
- struct Expr expr;
-};
-
-// Scope is a stack of alists
-// (((y . 20))
-// ((x . 10)
-// (name . "Alexey")))
-
-struct Scope create_scope(Gc *gc);
-
-struct Expr get_scope_value(const struct Scope *scope, struct Expr name);
-void set_scope_value(Gc *gc, struct Scope *scope, struct Expr name, struct Expr value);
-void push_scope_frame(Gc *gc, struct Scope *scope, struct Expr vars, struct Expr args);
-void pop_scope_frame(Gc *gc, struct Scope *scope);
-
-#endif // SCOPE_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include <string.h>
-
-#include "ebisp/gc.h"
-#include "ebisp/interpreter.h"
-#include "ebisp/builtins.h"
-#include "ebisp/scope.h"
-#include "ebisp/parser.h"
-
-#include "std.h"
-
-static struct Expr
-lambda(Gc *gc, struct Expr args, struct Expr body, struct Scope *scope)
-{
- return atom_as_expr(create_lambda_atom(gc, args, body, scope->expr));
-}
-
-static struct EvalResult
-quasiquote(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr expr = void_expr();
- struct EvalResult result = match_list(gc, "e", args, &expr);
- if (result.is_error) {
- return result;
- }
-
- const char *unquote = NULL;
- struct Expr unquote_expr = void_expr();
- result = match_list(gc, "qe", expr, &unquote, &unquote_expr);
-
- if (!result.is_error && strcmp(unquote, "unquote") == 0) {
- return eval(gc, scope, unquote_expr);
- } else if (cons_p(expr)) {
- struct EvalResult left = quasiquote(param, gc, scope, CONS(gc, CAR(expr), NIL(gc)));
- if (left.is_error) {
- return left;
- }
- struct EvalResult right = quasiquote(param, gc, scope, CONS(gc, CDR(expr), NIL(gc)));
- if (right.is_error) {
- return right;
- }
- return eval_success(CONS(gc, left.expr, right.expr));
- } else {
- return eval_success(expr);
- }
-}
-
-static struct EvalResult
-unquote(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
- (void) args;
-
- return eval_failure(STRING(gc, "Using unquote outside of quasiquote."));
-}
-
-static struct EvalResult
-greaterThan(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) param;
-
- // TODO(#1099): greaterThan does not support floats
-
- long int x1 = 0;
- struct Expr xs = void_expr();
-
- struct EvalResult result = match_list(gc, "d*", args, &x1, &xs);
- if (result.is_error) {
- return result;
- }
-
- bool sorted = true;
-
- while (!nil_p(xs) && sorted) {
- long int x2 = 0;
- result = match_list(gc, "d*", xs, &x2, NULL);
- if (result.is_error) {
- return result;
- }
-
- sorted = sorted && (x1 > x2);
- args = xs;
-
- result = match_list(gc, "d*", args, &x1, &xs);
- if (result.is_error) {
- return result;
- }
- }
-
- return eval_success(bool_as_expr(gc, sorted));
-}
-
-static struct EvalResult
-list_op(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) param;
-
- return eval_success(args);
-}
-
-static struct EvalResult
-plus_op(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- // TODO(#1100): plus_op does not support floats
-
- long int result = 0L;
-
- while (!nil_p(args)) {
- if (!cons_p(args)) {
- return wrong_argument_type(gc, "consp", args);
- }
-
- if (!integer_p(CAR(args))) {
- return wrong_argument_type(gc, "integerp", CAR(args));
- }
-
- result += CAR(args).atom->num;
- args = CDR(args);
- }
-
- return eval_success(INTEGER(gc, result));
-}
-
-static struct EvalResult
-mul_op(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- long int result = 1L;
-
- // TODO(#1101): mul_op does not support floats
-
- while (!nil_p(args)) {
- if (!cons_p(args)) {
- return wrong_argument_type(gc, "consp", args);
- }
-
- if (!integer_p(CAR(args))) {
- return wrong_argument_type(gc, "integerp", CAR(args));
- }
-
- result *= CAR(args).atom->num;
- args = CDR(args);
- }
-
- return eval_success(INTEGER(gc, result));
-}
-
-static struct EvalResult
-assoc_op(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr key = NIL(gc);
- struct Expr alist = NIL(gc);
- struct EvalResult result = match_list(gc, "ee", args, &key, &alist);
- if (result.is_error) {
- return result;
- }
-
- return eval_success(assoc(key, alist));
-}
-
-static struct EvalResult
-set(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- const char *name = NULL;
- struct Expr value = void_expr();
- struct EvalResult result = match_list(gc, "qe", args, &name, &value);
- if (result.is_error) {
- return result;
- }
-
- result = eval(gc, scope, value);
- if (result.is_error) {
- return result;
- }
-
- set_scope_value(gc, scope, SYMBOL(gc, name), result.expr);
-
- return eval_success(result.expr);
-}
-
-static struct EvalResult
-quote(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr expr = void_expr();
- struct EvalResult result = match_list(gc, "e", args, &expr);
- if (result.is_error) {
- return result;
- }
-
- return eval_success(expr);
-}
-
-static struct EvalResult
-begin(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr block = void_expr();
- struct EvalResult result = match_list(gc, "*", args, &block);
- if (result.is_error) {
- return result;
- }
-
- return eval_block(gc, scope, block);
-}
-
-static struct EvalResult
-defun(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr name = void_expr();
- struct Expr args_list = void_expr();
- struct Expr body = void_expr();
-
- struct EvalResult result = match_list(gc, "ee*", args, &name, &args_list, &body);
- if (result.is_error) {
- return result;
- }
-
- if (!list_of_symbols_p(args_list)) {
- return wrong_argument_type(gc, "list-of-symbolsp", args_list);
- }
-
- return eval(gc, scope,
- list(gc, "qee", "set", name,
- lambda(gc, args_list, body, scope)));
-}
-
-static struct EvalResult
-when(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr condition = void_expr();
- struct Expr body = void_expr();
-
- struct EvalResult result = match_list(
- gc, "e*", args, &condition, &body);
- if (result.is_error) {
- return result;
- }
-
- result = eval(gc, scope, condition);
- if (result.is_error) {
- return result;
- }
-
- if (!nil_p(result.expr)) {
- return eval_block(gc, scope, body);
- }
-
- return eval_success(NIL(gc));
-}
-
-static struct EvalResult
-lambda_op(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr args_list = void_expr();
- struct Expr body = void_expr();
-
- struct EvalResult result = match_list(gc, "e*", args, &args_list, &body);
- if (result.is_error) {
- return result;
- }
-
- if (!list_of_symbols_p(args_list)) {
- return wrong_argument_type(gc, "list-of-symbolsp", args_list);
- }
-
- return eval_success(lambda(gc, args_list, body, scope));
-}
-
-static struct EvalResult
-equal_op(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr obj1;
- struct Expr obj2;
- struct EvalResult result = match_list(gc, "ee", args, &obj1, &obj2);
- if (result.is_error) {
- return result;
- }
-
- if (equal(obj1, obj2)) {
- return eval_success(T(gc));
- } else {
- return eval_success(NIL(gc));
- }
-}
-
-static struct EvalResult
-load(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- const char *filename = NULL;
- struct EvalResult result = match_list(gc, "s", args, &filename);
- if (result.is_error) {
- return result;
- }
-
- struct ParseResult parse_result = read_all_exprs_from_file(gc, filename);
- if (parse_result.is_error) {
- /* TODO(#599): (load) does not provide position of the parse error */
- return read_error(gc, parse_result.error_message, 0);
- }
-
- return eval_block(gc, scope, parse_result.expr);
-}
-
-// TODO(#672): append does not work with arbitrary amount of arguments
-// TODO(#673): append is implemented recursively
-// It's very StackOverflow prone
-static struct EvalResult
-append(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- (void) param;
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr xs = void_expr();
- struct Expr ys = void_expr();
- struct EvalResult result = match_list(gc, "ee", args, &xs, &ys);
- if (result.is_error) {
- return result;
- }
-
- if (nil_p(xs)) {
- return eval_success(ys);
- }
-
- struct Expr xs1 = void_expr();
- struct Expr x = void_expr();
- result = match_list(gc, "e*", xs, &x, &xs1);
- if (result.is_error) {
- return result;
- }
-
- result = append(param, gc, scope, list(gc, "ee", xs1, ys));
- if (result.is_error) {
- return result;
- }
-
- return eval_success(CONS(gc, x, result.expr));
-}
-
-void load_std_library(Gc *gc, struct Scope *scope)
-{
- set_scope_value(gc, scope, SYMBOL(gc, "car"), NATIVE(gc, car, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, ">"), NATIVE(gc, greaterThan, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "+"), NATIVE(gc, plus_op, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "*"), NATIVE(gc, mul_op, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "list"), NATIVE(gc, list_op, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "t"), SYMBOL(gc, "t"));
- set_scope_value(gc, scope, SYMBOL(gc, "nil"), SYMBOL(gc, "nil"));
- set_scope_value(gc, scope, SYMBOL(gc, "assoc"), NATIVE(gc, assoc_op, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "quasiquote"), NATIVE(gc, quasiquote, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "set"), NATIVE(gc, set, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "quote"), NATIVE(gc, quote, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "begin"), NATIVE(gc, begin, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "defun"), NATIVE(gc, defun, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "when"), NATIVE(gc, when, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "lambda"), NATIVE(gc, lambda_op, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "λ"), NATIVE(gc, lambda_op, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "unquote"), NATIVE(gc, unquote, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "load"), NATIVE(gc, load, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "append"), NATIVE(gc, append, NULL));
- set_scope_value(gc, scope, SYMBOL(gc, "equal"), NATIVE(gc, equal_op, NULL));
-}
+++ /dev/null
-#ifndef STD_H_
-#define STD_H_
-
-void load_std_library(Gc *gc, struct Scope *scope);
-
-#endif // STD_H_
+++ /dev/null
-#include <stdio.h>
-#include <stdbool.h>
-#include "system/stacktrace.h"
-#include <ctype.h>
-#include <stdlib.h>
-
-#include "./tokenizer.h"
-
-static struct Token token(const char *begin, const char *end)
-{
- struct Token token = {
- .begin = begin,
- .end = end
- };
-
- return token;
-}
-
-static bool is_symbol_char(char x)
-{
- static const char forbidden_symbol_chars[] = {
- '(', ')', '"', '\'', ';', '`', ','
- };
- static const size_t n = sizeof(forbidden_symbol_chars) / sizeof(char);
-
- for (size_t i = 0; i < n; ++i) {
- if (x == forbidden_symbol_chars[i] || isspace(x)) {
- return false;
- }
- }
-
- return true;
-}
-
-static const char *skip_whitespace(const char *str)
-{
- trace_assert(str);
-
- while(*str != 0 && isspace(*str)) {
- str++;
- }
-
- return str;
-}
-
-static const char *next_quote(const char *str)
-{
- trace_assert(str);
-
- while(*str != 0 && *str != '"') {
- str++;
- }
-
- return str;
-}
-
-static const char *skip_until_newline(const char *str)
-{
- trace_assert(str);
-
- while(*str != 0 && *str != '\n') {
- str++;
- }
-
- return str;
-}
-
-static const char *next_non_symbol(const char *str)
-{
- trace_assert(str);
-
- while(*str != 0 && is_symbol_char(*str)) {
- str++;
- }
-
- return str;
-}
-
-struct Token next_token(const char *str)
-{
- trace_assert(str);
-
- str = skip_whitespace(str);
- if (*str == 0) {
- return token(str, str);
- }
-
- while (*str != 0 && *str == ';') {
- str = skip_until_newline(str + 1);
- str = skip_whitespace(str);
- }
-
- switch (*str) {
- case '(':
- case ')':
- case '.':
- case '\'':
- case '`':
- case ',':
- return token(str, str + 1);
-
- case '"': {
- const char *str_end = next_quote(str + 1);
- return token(str, *str_end == 0 ? str_end : str_end + 1);
- }
-
- default:
- return token(str, next_non_symbol(str + 1));
- }
-}
+++ /dev/null
-#ifndef TOKENIZER_H_
-#define TOKENIZER_H_
-
-struct Token
-{
- const char *begin;
- const char *end;
-};
-
-struct Token next_token(const char *str);
-
-#endif // TOKENIZER_H_
#include "ui/console.h"
#include "ui/edit_field.h"
#include "system/str.h"
-#include "ebisp/builtins.h"
-#include "broadcast.h"
#include "sdl/texture.h"
#include "game/level/level_editor/background_layer.h"
#include "game/level/level_editor.h"
Lt *lt;
Game_state state;
- Broadcast *broadcast;
Sprite_font *font;
LevelPicker *level_picker;
LevelEditor *level_editor;
}
game->lt = lt;
-
- game->broadcast = PUSH_LT(
- lt,
- create_broadcast(game),
- destroy_broadcast);
- if (game->broadcast == NULL) {
- RETURN_LT(lt, NULL);
- }
-
game->font = PUSH_LT(
lt,
create_sprite_font_from_file(
game->level = PUSH_LT(
game->lt,
create_level_from_level_editor(
- game->level_editor,
- game->broadcast),
+ game->level_editor),
destroy_level);
} else {
game->level = RESET_LT(
game->lt,
game->level,
create_level_from_level_editor(
- game->level_editor,
- game->broadcast));
+ game->level_editor));
}
if (game->level == NULL) {
game->lt,
game->level,
create_level_from_level_editor(
- game->level_editor,
- game->broadcast));
+ game->level_editor));
if (game->level == NULL) {
game_switch_state(game, GAME_STATE_QUIT);
return -1;
game->level = PUSH_LT(
game->lt,
create_level_from_level_editor(
- game->level_editor,
- game->broadcast),
+ game->level_editor),
destroy_level);
} else {
game->level = RESET_LT(
game->lt,
game->level,
create_level_from_level_editor(
- game->level_editor,
- game->broadcast));
+ game->level_editor));
}
if (game->level == NULL) {
game->lt,
game->level,
create_level_from_level_editor(
- game->level_editor,
- game->broadcast));
+ game->level_editor));
if (game->level == NULL) {
return -1;
}
return game->state == GAME_STATE_QUIT;
}
-struct EvalResult
-game_send(Game *game, Gc *gc, struct Scope *scope,
- struct Expr path)
-{
- trace_assert(game);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "q*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- if (strcmp(target, "level") == 0) {
- return level_send(game->level, gc, scope, rest);
- } else if (strcmp(target, "menu") == 0) {
- level_picker_clean_selection(game->level_picker);
- game_switch_state(game, GAME_STATE_LEVEL_PICKER);
- return eval_success(NIL(gc));
- }
-
- return unknown_target(gc, "game", target);
-}
-
// Private Functions
static int game_render_cursor(const Game *game)
#include <SDL.h>
#include "game/sound_samples.h"
-#include "ebisp/expr.h"
typedef struct Game Game;
int game_over_check(const Game *game);
-struct EvalResult
-game_send(Game *game, Gc *gc, struct Scope *scope, struct Expr path);
-
#endif // GAME_H_
#include <SDL.h>
#include "system/stacktrace.h"
-#include "broadcast.h"
#include "color.h"
-#include "ebisp/builtins.h"
-#include "ebisp/interpreter.h"
#include "game/camera.h"
#include "game/level.h"
#include "game/level/background.h"
#include "system/nth_alloc.h"
#include "system/str.h"
#include "game/level/level_editor.h"
-#include "game/level/script.h"
#include "ui/console.h"
#define LEVEL_GRAVITY 1500.0f
Boxes *boxes;
Labels *labels;
Regions *regions;
- Script *supa_script;
Console *console;
int console_enabled;
};
-Level *create_level_from_level_editor(const LevelEditor *level_editor,
- Broadcast *broadcast)
+Level *create_level_from_level_editor(const LevelEditor *level_editor)
{
trace_assert(level_editor);
- trace_assert(broadcast);
Lt *lt = create_lt();
lt,
create_player_from_player_layer(
&level_editor->player_layer,
- level->rigid_bodies,
- broadcast),
+ level->rigid_bodies),
destroy_player);
if (level->player == NULL) {
RETURN_LT(lt, NULL);
RETURN_LT(lt, NULL);
}
- level->supa_script = PUSH_LT(
- lt,
- create_script_from_string(
- broadcast,
- level_editor->supa_script_source),
- destroy_script);
- if (level->supa_script == NULL) {
- log_fail("Could not construct Supa Script for the level\n");
- RETURN_LT(lt, NULL);
- }
-
level->console = PUSH_LT(
lt,
- create_console(broadcast),
+ create_console(),
destroy_console);
if (level->console == NULL) {
RETURN_LT(lt, NULL);
player_hide_goals(level->player, level->goals);
player_die_from_lava(level->player, level->lava);
- regions_player_enter(level->regions, level->player, level->supa_script);
- regions_player_leave(level->regions, level->player, level->supa_script);
+ regions_player_enter(level->regions, level->player);
+ regions_player_leave(level->regions, level->player);
goals_update(level->goals, delta_time);
lava_update(level->lava, delta_time);
case SDLK_w:
case SDLK_UP:
case SDLK_SPACE: {
- player_jump(level->player, level->supa_script);
+ player_jump(level->player);
} break;
case SDLK_p: {
case SDL_JOYBUTTONDOWN:
if (event->jbutton.button == 1) {
- player_jump(level->player, level->supa_script);
+ player_jump(level->player);
}
break;
}
labels_enter_camera_event(level->labels, camera);
return 0;
}
-
-struct EvalResult level_send(Level *level, Gc *gc, struct Scope *scope, struct Expr path)
-{
- trace_assert(level);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "q*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- if (strcmp(target, "goal") == 0) {
- return goals_send(level->goals, gc, scope, rest);
- } else if (strcmp(target, "label") == 0) {
- return labels_send(level->labels, gc, scope, rest);
- } else if (strcmp(target, "box") == 0) {
- return boxes_send(level->boxes, gc, scope, rest);
- } else if (strcmp(target, "body-push") == 0) {
- long int id = 0, x = 0, y = 0;
- res = match_list(gc, "ddd", rest, &id, &x, &y);
- if (res.is_error) {
- return res;
- }
-
- rigid_bodies_apply_force(level->rigid_bodies, (size_t) id, vec((float) x, (float) y));
-
- return eval_success(NIL(gc));
- } else if (strcmp(target, "edit") == 0) {
- return eval_success(NIL(gc));
- }
-
- return unknown_target(gc, "level", target);
-}
#include "game/level/platforms.h"
#include "game/level/player.h"
#include "sound_samples.h"
-#include "ebisp/expr.h"
-typedef struct Broadcast Broadcast;
typedef struct Level Level;
typedef struct LevelEditor LevelEditor;
-Level *create_level_from_level_editor(const LevelEditor *level_editor,
- Broadcast *broadcast);
+Level *create_level_from_level_editor(const LevelEditor *level_editor);
void destroy_level(Level *level);
int level_render(const Level *level, const Camera *camera);
void level_toggle_pause_mode(Level *level);
-struct EvalResult level_send(Level *level, Gc *gc, struct Scope *scope, struct Expr path);
-
#endif // LEVEL_H_
#include "system/stacktrace.h"
-#include "broadcast.h"
#include "dynarray.h"
-#include "ebisp/builtins.h"
-#include "ebisp/interpreter.h"
#include "game/level/boxes.h"
#include "game/level/level_editor/rect_layer.h"
#include "game/level/player.h"
return 0;
}
-struct EvalResult
-boxes_send(Boxes *boxes, Gc *gc, struct Scope *scope, struct Expr path)
-{
- trace_assert(boxes);
- trace_assert(gc);
- trace_assert(scope);
-
- struct Expr target = void_expr();
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "e*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- if (symbol_p(target)) {
- const char *action = target.atom->str;
-
- if (strcmp(action, "new") == 0) {
- struct Expr optional_args = void_expr();
- long int x, y, w, h;
- res = match_list(gc, "dddd*", rest, &x, &y, &w, &h, &optional_args);
- if (res.is_error) {
- return res;
- }
-
- Color color = rgba(rand_float(1.0f), rand_float(1.0f), rand_float(1.0f), 1.0f);
- if (!nil_p(optional_args)) {
- const char *color_hex = NULL;
- res = match_list(gc, "s*", optional_args, &color_hex, NULL);
- color = hexstr(color_hex);
- }
-
- boxes_add_box(boxes, rect((float) x, (float) y, (float) w, (float) h), color);
-
- return eval_success(NIL(gc));
- } else if (strcmp(action, "coord") == 0) {
- const char *box_id = NULL;
- res = match_list(gc, "s", rest, &box_id);
- if (res.is_error) {
- return res;
- }
-
- size_t n = dynarray_count(boxes->boxes_ids);
- RigidBodyId *body_ids = dynarray_data(boxes->body_ids);
- for (size_t i = 0; i < n; ++i) {
- if (strcmp(dynarray_pointer_at(boxes->boxes_ids, i), box_id) == 0) {
- Rect hitbox = rigid_bodies_hitbox(boxes->rigid_bodies, body_ids[i]);
- return eval_success(
- CONS(gc,
- INTEGER(gc, (long int)hitbox.x),
- INTEGER(gc, (long int)hitbox.y)));
- }
- }
-
- return eval_failure(SYMBOL(gc, "box-not-found"));
- }
-
- return unknown_target(gc, "box", action);
- }
-
- return wrong_argument_type(gc, "string-or-symbol-p", target);
-}
-
-
int boxes_delete_at(Boxes *boxes, Vec2f position)
{
trace_assert(boxes);
#include "game/camera.h"
#include "game/level/platforms.h"
#include "lava.h"
-#include "ebisp/expr.h"
typedef struct Boxes Boxes;
typedef struct Player Player;
int boxes_add_box(Boxes *boxes, Rect rect, Color color);
int boxes_delete_at(Boxes *boxes, Vec2f position);
-struct EvalResult
-boxes_send(Boxes *boxes, Gc *gc, struct Scope *scope, struct Expr path);
-
#endif // BOXES_H_
#include <SDL.h>
-#include "broadcast.h"
-#include "ebisp/interpreter.h"
#include "game/level/level_editor/point_layer.h"
#include "goals.h"
#include "math/pi.h"
}
}
-static struct EvalResult
-goals_action(Goals *goals, size_t index, Gc *gc, struct Scope *scope, struct Expr path)
-{
- trace_assert(goals);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct EvalResult res = match_list(gc, "q*", path, &target, NULL);
- if (res.is_error) {
- return res;
- }
-
- if (strcmp(target, "show") == 0) {
- goals->visible[index] = true;
- return eval_success(NIL(gc));
- } else if (strcmp(target, "hide") == 0) {
- goals->visible[index] = false;
- return eval_success(NIL(gc));
- }
-
- return unknown_target(gc, goals->ids[index], target);
-}
-
-struct EvalResult
-goals_send(Goals *goals, Gc *gc, struct Scope *scope, struct Expr path)
-{
- trace_assert(goals);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "s*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- for (size_t i = 0; i < goals->count; ++i) {
- if (strcmp(target, goals->ids[i]) == 0) {
- return goals_action(goals, i, gc, scope, rest);
- }
- }
-
- return unknown_target(gc, "goals", target);
-}
-
/* Private Functions */
static int goals_is_goal_hidden(const Goals *goals, size_t i)
#include "game/camera.h"
#include "game/level/player.h"
#include "game/sound_samples.h"
-#include "ebisp/expr.h"
typedef struct Goals Goals;
typedef struct LineStream LineStream;
void goals_cue(Goals *goals,
const Camera *camera);
-struct EvalResult goals_send(Goals *goals, Gc *gc, struct Scope *scope, struct Expr path);
-
#endif // GOALS_H_
#include <stdio.h>
#include <stdbool.h>
-#include "broadcast.h"
-#include "ebisp/interpreter.h"
#include "game/camera.h"
#include "game/level/labels.h"
#include "game/level/level_editor/label_layer.h"
}
}
}
-
-static struct EvalResult
-labels_action(Labels *labels,
- size_t index,
- Gc *gc,
- struct Scope *scope,
- struct Expr path)
-{
- trace_assert(labels);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "q*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- if (strcmp(target, "hide") == 0) {
- if (labels->states[index] != LABEL_STATE_HIDDEN) {
- labels->states[index] = LABEL_STATE_HIDDEN;
- labels->alphas[index] = 1.0f;
- labels->delta_alphas[index] = -3.0f;
- }
- return eval_success(NIL(gc));
- }
-
- return unknown_target(gc, labels->ids + index * LABEL_MAX_ID_SIZE, target);
-}
-
-struct EvalResult
-labels_send(Labels *labels, Gc *gc, struct Scope *scope, struct Expr path)
-{
- trace_assert(labels);
- trace_assert(gc);
- trace_assert(scope);
-
- const char *target = NULL;
- struct Expr rest = void_expr();
- struct EvalResult res = match_list(gc, "s*", path, &target, &rest);
- if (res.is_error) {
- return res;
- }
-
- for (size_t i = 0; i < labels->count; ++i) {
- if (strcmp(target, labels->ids + i * LABEL_MAX_ID_SIZE) == 0) {
- return labels_action(labels, i, gc, scope, rest);
- }
- }
-
- return unknown_target(gc, "label", target);
-}
#include "math/vec.h"
#include "color.h"
-#include "ebisp/expr.h"
typedef struct Labels Labels;
typedef struct LineStream LineStream;
void labels_enter_camera_event(Labels *label,
const Camera *camera);
-struct EvalResult
-labels_send(Labels *labels, Gc *gc, struct Scope *scope, struct Expr path);
-
#endif // LABELS_H_
#include <SDL.h>
#include "game/level/explosion.h"
-#include "game/level/script.h"
#include "game/level/rigid_bodies.h"
#include "goals.h"
#include "math/vec.h"
#include "system/lt.h"
#include "system/nth_alloc.h"
#include "system/stacktrace.h"
-#include "ebisp/builtins.h"
#include "config.h"
#define PLAYER_WIDTH 25.0f
};
Player *create_player_from_player_layer(const PlayerLayer *player_layer,
- RigidBodies *rigid_bodies,
- Broadcast *broadcast)
+ RigidBodies *rigid_bodies)
{
trace_assert(player_layer);
trace_assert(rigid_bodies);
- trace_assert(broadcast);
Lt *lt = create_lt();
rigid_bodies_move(player->rigid_bodies, player->alive_body_id, vec(0.0f, 0.0f));
}
-void player_jump(Player *player, Script *supa_script)
+void player_jump(Player *player)
{
trace_assert(player);
- trace_assert(supa_script);
if (rigid_bodies_touches_ground(player->rigid_bodies, player->alive_body_id)) {
player->jump_threshold = 0;
player->alive_body_id,
vec(0.0f, -PLAYER_JUMP));
player->jump_threshold++;
-
- if (script_has_scope_value(supa_script, "on-player-jump")) {
- Gc *gc = script_gc(supa_script);
- script_eval(supa_script, list(gc, "q", "on-player-jump"));
- }
}
}
typedef struct Player Player;
typedef struct Goals Goals;
typedef struct LineStream LineStream;
-typedef struct Script Script;
-typedef struct Broadcast Broadcast;
typedef struct RigidBodies RigidBodies;
Player *create_player_from_player_layer(const PlayerLayer *player_layer,
- RigidBodies *rigid_bodies,
- Broadcast *broadcast);
+ RigidBodies *rigid_bodies);
void destroy_player(Player * player);
int player_render(const Player * player,
void player_move_left(Player *player);
void player_move_right(Player *player);
void player_stop(Player *player);
-void player_jump(Player *player, Script *supa_script);
+void player_jump(Player *player);
void player_die(Player *player);
void player_focus_camera(Player *player,
#include "system/stacktrace.h"
-#include "ebisp/gc.h"
-#include "ebisp/interpreter.h"
-#include "ebisp/parser.h"
-#include "ebisp/scope.h"
#include "player.h"
#include "regions.h"
-#include "script.h"
#include "system/str.h"
#include "system/line_stream.h"
#include "system/log.h"
RETURN_LT0(regions->lt);
}
-void regions_player_enter(Regions *regions, Player *player, Script *supa_script)
+void regions_player_enter(Regions *regions, Player *player)
{
trace_assert(regions);
trace_assert(player);
if (regions->states[i] == RS_PLAYER_OUTSIDE &&
player_overlaps_rect(player, regions->rects[i])) {
regions->states[i] = RS_PLAYER_INSIDE;
-
- Gc *gc = script_gc(supa_script);
- if (script_has_scope_value(supa_script, "on-region-enter")) {
- script_eval(
- supa_script,
- list(gc, "qs",
- "on-region-enter",
- regions->ids + i * ID_MAX_SIZE));
- }
}
}
}
-void regions_player_leave(Regions *regions, Player *player, Script *supa_script)
+void regions_player_leave(Regions *regions, Player *player)
{
trace_assert(regions);
trace_assert(player);
- trace_assert(supa_script);
for (size_t i = 0; i < regions->count; ++i) {
if (regions->states[i] == RS_PLAYER_INSIDE &&
!player_overlaps_rect(player, regions->rects[i])) {
regions->states[i] = RS_PLAYER_OUTSIDE;
- Gc *gc = script_gc(supa_script);
- if (script_has_scope_value(supa_script, "on-region-leave")) {
- script_eval(
- supa_script,
- list(gc, "qs",
- "on-region-leave",
- regions->ids + i * ID_MAX_SIZE));
- }
}
}
}
int regions_render(Regions *regions, const Camera *camera);
-void regions_player_enter(Regions *regions, Player *player, Script *supa_script);
-void regions_player_leave(Regions *regions, Player *player, Script *supa_script);
+void regions_player_enter(Regions *regions, Player *player);
+void regions_player_leave(Regions *regions, Player *player);
#endif // REGIONS_H_
+++ /dev/null
-#include "system/stacktrace.h"
-#include "ebisp/gc.h"
-#include "ebisp/interpreter.h"
-#include "ebisp/parser.h"
-#include "ebisp/scope.h"
-#include "ebisp/std.h"
-#include "game/level.h"
-#include "script.h"
-#include "system/str.h"
-#include "system/line_stream.h"
-#include "system/log.h"
-#include "system/log_script.h"
-#include "system/lt.h"
-#include "system/nth_alloc.h"
-#include "ui/console.h"
-#include "broadcast.h"
-
-struct Script
-{
- Lt *lt;
- Gc *gc;
- struct Scope scope;
-};
-
-static Script *create_script(Broadcast *broadcast, const char *source_code)
-{
- trace_assert(source_code);
-
- Lt *lt = create_lt();
-
- Script *script = PUSH_LT(lt, nth_calloc(1, sizeof(Script)), free);
- if (script == NULL) {
- RETURN_LT(lt, NULL);
- }
- script->lt = lt;
-
- script->gc = PUSH_LT(lt, create_gc(), destroy_gc);
- if (script->gc == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- script->scope = create_scope(script->gc);
- load_std_library(script->gc, &script->scope);
- load_log_library(script->gc, &script->scope);
- broadcast_load_library(broadcast, script->gc, &script->scope);
-
- struct ParseResult parse_result =
- read_all_exprs_from_string(
- script->gc,
- source_code);
- if (parse_result.is_error) {
- log_fail("Parsing error: %s\n", parse_result.error_message);
- RETURN_LT(lt, NULL);
- }
-
- struct EvalResult eval_result = eval(
- script->gc,
- &script->scope,
- CONS(script->gc,
- SYMBOL(script->gc, "begin"),
- parse_result.expr));
- if (eval_result.is_error) {
- print_expr_as_sexpr(stderr, eval_result.expr);
- log_fail("\n");
- RETURN_LT(lt, NULL);
- }
-
- gc_collect(script->gc, script->scope.expr);
-
- return script;
-}
-
-Script *create_script_from_string(Broadcast *broadcast, const char *source_code)
-{
- return create_script(broadcast, string_duplicate(source_code, NULL));
-}
-
-Script *create_script_from_line_stream(LineStream *line_stream, Broadcast *broadcast)
-{
- trace_assert(line_stream);
-
- const char *source_code = line_stream_collect_until_end(line_stream);
- if (source_code == NULL) {
- return NULL;
- }
-
- return create_script(broadcast, source_code);
-}
-
-void destroy_script(Script *script)
-{
- trace_assert(script);
- RETURN_LT0(script->lt);
-}
-
-int script_eval(Script *script, struct Expr expr)
-{
- trace_assert(script);
-
- struct EvalResult eval_result = eval(
- script->gc,
- &script->scope,
- expr);
- if (eval_result.is_error) {
- log_fail("Evaluation error: ");
- /* TODO(#521): Evalation error is prepended with `[FAIL]` at the end of the message */
- /* TODO(#486): print_expr_as_sexpr could not be easily integrated with log_fail */
- print_expr_as_sexpr(stderr, eval_result.expr);
- log_fail("\n");
- return -1;
- }
-
- gc_collect(script->gc, script->scope.expr);
-
- return 0;
-}
-
-bool script_has_scope_value(const Script *script, const char *name)
-{
- return !nil_p(
- get_scope_value(
- &script->scope,
- SYMBOL(script->gc, name)));
-}
-
-Gc *script_gc(const Script *script)
-{
- return script->gc;
-}
+++ /dev/null
-#ifndef SCRIPT_H_
-#define SCRIPT_H_
-
-#include <stdbool.h>
-#include "ebisp/expr.h"
-
-typedef struct Script Script;
-typedef struct LineStream LineStream;
-typedef struct Broadcast Broadcast;
-
-Script *create_script_from_string(Broadcast *broadcast, const char *source);
-Script *create_script_from_line_stream(LineStream *line_stream,
- Broadcast *broadcast);
-void destroy_script(Script *script);
-
-// TODO(#881): script_eval should return EvalResult and it should be handled properly everywhere
-int script_eval(Script *script, struct Expr expr);
-
-bool script_has_scope_value(const Script *script, const char *name);
-
-Gc *script_gc(const Script *script);
-
-#endif // SCRIPT_H_
+++ /dev/null
-#include "system/stacktrace.h"
-
-#include "ebisp/gc.h"
-#include "ebisp/scope.h"
-#include "ebisp/interpreter.h"
-#include "log_script.h"
-#include "log.h"
-
-static struct EvalResult
-print(void *param, Gc *gc, struct Scope *scope, struct Expr args)
-{
- trace_assert(gc);
- trace_assert(scope);
- (void) param;
-
- const char *s = NULL;
- struct EvalResult result = match_list(gc, "s", args, &s);
- if (result.is_error) {
- return result;
- }
-
- log_info("%s\n", s);
-
- return eval_success(NIL(gc));
-}
-
-void load_log_library(Gc *gc, struct Scope *scope)
-{
- set_scope_value(gc, scope, SYMBOL(gc, "print"), NATIVE(gc, print, NULL));
-}
+++ /dev/null
-#ifndef LOG_SCRIPT_H_
-#define LOG_SCRIPT_H_
-
-void load_log_library(Gc *gc, struct Scope *scope);
-
-#endif // LOG_SCRIPT_H_
#include "system/stacktrace.h"
-#include "ebisp/gc.h"
-#include "ebisp/interpreter.h"
-#include "ebisp/parser.h"
-#include "ebisp/scope.h"
-#include "ebisp/std.h"
#include "game/level.h"
#include "sdl/renderer.h"
#include "system/log.h"
-#include "system/log_script.h"
#include "system/lt.h"
#include "system/nth_alloc.h"
#include "ui/console.h"
#include "ui/console_log.h"
#include "ui/edit_field.h"
#include "ui/history.h"
-#include "broadcast.h"
#define FONT_WIDTH_SCALE 3.0f
#define FONT_HEIGHT_SCALE 3.0f
#define CONSOLE_ALPHA (0.80f)
#define CONSOLE_BACKGROUND (rgba(0.20f, 0.20f, 0.20f, CONSOLE_ALPHA))
#define CONSOLE_FOREGROUND (rgba(0.80f, 0.80f, 0.80f, CONSOLE_ALPHA))
-#define CONSOLE_ERROR (rgba(0.80f, 0.50f, 0.50f, CONSOLE_ALPHA))
-
-#define CONSOLE_EVAL_RESULT_SIZE 256
struct Console
{
Lt *lt;
- Gc *gc;
- struct Scope scope;
Edit_field *edit_field;
Console_Log *console_log;
History *history;
};
/* TODO(#356): Console does not support autocompletion */
-/* TODO(#357): Console does not show the state of the GC of the script */
/* TODO(#358): Console does not support copy, cut, paste operations */
-Console *create_console(Broadcast *broadcast)
+Console *create_console(void)
{
- trace_assert(broadcast);
-
Lt *lt = create_lt();
Console *console = PUSH_LT(lt, nth_calloc(1, sizeof(Console)), free);
}
console->lt = lt;
- console->gc = PUSH_LT(lt, create_gc(), destroy_gc);
- if (console->gc == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- console->scope.expr = CONS(console->gc,
- NIL(console->gc),
- NIL(console->gc));
-
- load_std_library(console->gc, &console->scope);
- load_log_library(console->gc, &console->scope);
- /* TODO(#669): how to report EvalResult error from create_console? */
- broadcast_load_library(broadcast, console->gc, &console->scope);
-
console->edit_field = PUSH_LT(
lt,
create_edit_field(
return -1;
}
- while (*source_code != 0) {
- struct ParseResult parse_result = read_expr_from_string(console->gc,
- source_code);
-
- if (parse_result.is_error) {
- if (console_log_push_line(console->console_log, parse_result.error_message, CONSOLE_ERROR)) {
- return -1;
- }
-
- edit_field_clean(console->edit_field);
-
- return 0;
- }
-
- struct EvalResult eval_result = eval(
- console->gc,
- &console->scope,
- parse_result.expr);
-
- char buffer[CONSOLE_EVAL_RESULT_SIZE];
-
- if (expr_as_sexpr(
- eval_result.expr,
- buffer,
- CONSOLE_EVAL_RESULT_SIZE) < 0) {
- return -1;
- }
-
- if (console_log_push_line(console->console_log,
- buffer,
- eval_result.is_error ?
- CONSOLE_ERROR :
- CONSOLE_FOREGROUND)) {
- return -1;
- }
-
- source_code = next_token(parse_result.end).begin;
- }
-
- gc_collect(console->gc, console->scope.expr);
edit_field_clean(console->edit_field);
return 0;
#define CONSOLE_H_
#include <SDL.h>
-#include "ebisp/interpreter.h"
typedef struct Console Console;
-typedef struct Broadcast Broadcast;
typedef struct Sprite_font Sprite_font;
-Console *create_console(Broadcast *broadcast);
+Console *create_console(void);
void destroy_console(Console *console);
int console_handle_event(Console *console,
+++ /dev/null
-#ifndef INTERPRETER_SUITE_H_
-#define INTERPRETER_SUITE_H_
-
-#include "test.h"
-#include "ebisp/builtins.h"
-#include "ebisp/expr.h"
-#include "ebisp/interpreter.h"
-
-TEST(equal_test)
-{
- Gc *gc = create_gc();
-
- struct Expr nil1 = NIL(gc);
- struct Expr nil2 = NIL(gc);
- ASSERT_TRUE(equal(nil1, nil2), {
- fprintf(stderr, "Expected: ");
- print_expr_as_sexpr(stderr, nil1);
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Actual: ");
- print_expr_as_sexpr(stderr, nil2);
- fprintf(stderr, "\n");
- });
-
- struct Expr list1 =
- CONS(gc, SYMBOL(gc, "a"),
- CONS(gc, SYMBOL(gc, "b"),
- CONS(gc, SYMBOL(gc, "c"),
- NIL(gc))));
- struct Expr list2 =
- CONS(gc, SYMBOL(gc, "a"),
- CONS(gc, SYMBOL(gc, "b"),
- CONS(gc, SYMBOL(gc, "c"),
- NIL(gc))));
- ASSERT_TRUE(equal(list1, list2), {
- fprintf(stderr, "Expected: ");
- print_expr_as_sexpr(stderr, list1);
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Actual: ");
- print_expr_as_sexpr(stderr, list2);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(assoc_test)
-{
- Gc *gc = create_gc();
-
- struct Expr nil = NIL(gc);
-
- struct Expr a = SYMBOL(gc, "a");
- struct Expr b = SYMBOL(gc, "b");
- struct Expr c = SYMBOL(gc, "c");
-
- struct Expr a_pair = CONS(gc, a, INTEGER(gc, 10));
- struct Expr b_pair = CONS(gc, b, INTEGER(gc, 20));
- struct Expr c_pair = CONS(gc, c, INTEGER(gc, 30));
-
- struct Expr alist =
- CONS(gc, a_pair,
- CONS(gc, b_pair,
- CONS(gc, c_pair, nil)));
-
- struct Expr assoc_result = assoc(a, alist);
-
- ASSERT_TRUE(equal(a_pair, assoc_result), {
- fprintf(stderr, "Expected: ");
- print_expr_as_sexpr(stderr, a_pair);
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Actual: ");
- print_expr_as_sexpr(stderr, assoc_result);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(match_list_test)
-{
- Gc *gc = create_gc();
-
- struct Expr input = list(
- gc, "dsqe",
- 42,
- "hello",
- "world",
- CONS(gc, INTEGER(gc, 1), INTEGER(gc, 2)));
-
- long int d = 0;
- const char *s = NULL;
- const char *q = NULL;
- struct Expr e = NIL(gc);
-
- struct EvalResult result = match_list(gc, "dsqe", input, &d, &s, &q, &e);
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr, "Unpack failed: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- ASSERT_TRUE(d == 42, {
- fprintf(stderr, "Expected: 42, Actual: %ld\n", d);
- });
- ASSERT_TRUE(strcmp(s, "hello") == 0, {
- fprintf(stderr, "Expected: hello, Actual: %s\n", s);
- });
- ASSERT_TRUE(strcmp(q, "world") == 0, {
- fprintf(stderr, "Expected: world, Actual: %s\n", q);
- });
- ASSERT_TRUE(equal(e, CONS(gc, INTEGER(gc, 1), INTEGER(gc, 2))), {
- fprintf(stderr, "Expected: ");
- print_expr_as_sexpr(stderr, CONS(gc, INTEGER(gc, 1), INTEGER(gc, 2)));
- fprintf(stderr, ", Actual: ");
- print_expr_as_sexpr(stderr, e);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(match_list_empty_list_test)
-{
- Gc *gc = create_gc();
-
- long int d = 0;
- struct EvalResult result = match_list(gc, "d", NIL(gc), &d);
-
- ASSERT_TRUE(result.is_error, {
- fprintf(stderr, "Unpack did not fail\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(match_list_head_tail_test)
-{
- Gc *gc = create_gc();
-
- struct Expr input = list(gc, "dddd", 1, 2, 3, 4);
-
- long int x = 0;
- struct Expr xs = NIL(gc);
-
- struct EvalResult result = match_list(gc, "d*", input, &x, &xs);
- ASSERT_TRUE(!result.is_error, {
- fprintf(stderr, "Could not unpack input: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- ASSERT_TRUE(x == 1, {
- fprintf(stderr, "Expected: 1, Actual: %ld\n", x);
- });
-
- ASSERT_TRUE(equal(xs, list(gc, "ddd", 2, 3, 4)), {
- fprintf(stderr, "Expected: (2 3 4), Actual: ");
- print_expr_as_sexpr(stderr, xs);
- fprintf(stderr, "\n");
- })
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(match_list_wildcard_test)
-{
- Gc *gc = create_gc();
-
- struct Expr input = list(
- gc, "dddd", 1, 2, 3, 4);
-
- long int x = 0, y = 0;
- struct EvalResult result = match_list(gc, "dddd", input, &x, NULL, &y, NULL);
- ASSERT_TRUE(!result.is_error, {
- fprintf(stderr, "Matching failed: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- ASSERT_LONGINTEQ(1L, x);
- ASSERT_LONGINTEQ(3L, y);
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(match_list_singleton_tail_test)
-{
- Gc *gc = create_gc();
-
- struct Expr input = list(gc, "d", 1);
- long int x;
- struct Expr xs = NIL(gc);
- struct EvalResult res = match_list(gc, "d*", input, &x, &xs);
-
- ASSERT_TRUE(!res.is_error, {
- fprintf(stderr, "Matching failed: ");
- print_expr_as_sexpr(stderr, res.expr);
- fprintf(stderr, "\n");
- });
-
- ASSERT_LONGINTEQ(1L, x);
- ASSERT_TRUE(nil_p(xs), {
- fprintf(stderr, "Tail doesn't appear to be NIL: ");
- print_expr_as_sexpr(stderr, xs);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST_SUITE(interpreter_suite)
-{
- TEST_RUN(equal_test);
- TEST_RUN(assoc_test);
- TEST_RUN(match_list_test);
- TEST_RUN(match_list_empty_list_test);
- TEST_RUN(match_list_head_tail_test);
- TEST_RUN(match_list_wildcard_test);
- TEST_RUN(match_list_singleton_tail_test);
-
- return 0;
-}
-
-#endif // INTERPRETER_SUITE_H_
+++ /dev/null
-#include "test.h"
-#include "tokenizer_suite.h"
-#include "parser_suite.h"
-#include "interpreter_suite.h"
-#include "scope_suite.h"
-
-TEST_MAIN()
-{
- TEST_RUN(tokenizer_suite);
- TEST_RUN(parser_suite);
- TEST_RUN(interpreter_suite);
- TEST_RUN(scope_suite);
-
- return 0;
-}
+++ /dev/null
-#ifndef PARSER_SUITE_H_
-#define PARSER_SUITE_H_
-
-#include "test.h"
-#include "ebisp/parser.h"
-#include "ebisp/gc.h"
-#include "ebisp/builtins.h"
-
-TEST(read_expr_from_file_test)
-{
- Gc *gc = create_gc();
-
- struct ParseResult result = read_expr_from_file(gc, "test-data/simple-sum.ebi");
-
- ASSERT_TRUE(!result.is_error, {
- fprintf(stderr,
- "Parsing failed: %s",
- result.error_message);
- });
-
- struct Expr head = result.expr;
-
- struct Expr expr = head;
- ASSERT_INTEQ(EXPR_CONS, expr.type);
- ASSERT_INTEQ(EXPR_ATOM, expr.cons->car.type);
- ASSERT_INTEQ(ATOM_SYMBOL, expr.cons->car.atom->type);
- ASSERT_STREQ("+", expr.cons->car.atom->sym);
-
- expr = expr.cons->cdr;
- ASSERT_INTEQ(EXPR_CONS, expr.type);
- ASSERT_INTEQ(EXPR_ATOM, expr.cons->car.type);
- ASSERT_INTEQ(ATOM_INTEGER, expr.cons->car.atom->type);
- ASSERT_LONGINTEQ(1L, expr.cons->car.atom->num);
-
- expr = expr.cons->cdr;
- ASSERT_INTEQ(EXPR_CONS, expr.type);
- ASSERT_INTEQ(EXPR_ATOM, expr.cons->car.type);
- ASSERT_INTEQ(ATOM_INTEGER, expr.cons->car.atom->type);
- ASSERT_LONGINTEQ(2L, expr.cons->car.atom->num);
-
- expr = expr.cons->cdr;
- ASSERT_INTEQ(EXPR_CONS, expr.type);
- ASSERT_INTEQ(EXPR_ATOM, expr.cons->car.type);
- ASSERT_INTEQ(ATOM_INTEGER, expr.cons->car.atom->type);
- ASSERT_LONGINTEQ(3L, expr.cons->car.atom->num);
-
- expr = expr.cons->cdr;
- ASSERT_INTEQ(EXPR_ATOM, expr.type);
- ASSERT_INTEQ(ATOM_SYMBOL, expr.atom->type);
- ASSERT_STREQ("nil", expr.atom->sym);
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(parse_reals_test)
-{
- Gc *gc = create_gc();
-
- const char *input = "3.1415";
- struct ParseResult result = read_expr_from_string(gc, input);
- struct Expr expected = REAL(gc, 3.1415f);
-
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr, "Parsing failed: %s\n", result.error_message);
- });
-
- ASSERT_TRUE(equal(expected, result.expr), {
- fprintf(stderr, "Expected: ");
- print_expr_as_sexpr(stderr, expected);
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Actual: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(parse_real_pair_test)
-{
- Gc *gc = create_gc();
-
- const char *input[] = {
- "(2 . 2)",
- "(2. 2)",
- // TODO(#1104): parse_real_pair_test does not parse (2 .2) as expected
-
- // "(2 .2)",
- "(2.2)"
- };
-
- struct Expr expected[] = {
- CONS(gc, INTEGER(gc, 2), INTEGER(gc, 2)),
- CONS(gc, REAL(gc, 2.0f), CONS(gc, INTEGER(gc, 2), NIL(gc))),
- // CONS(gc, INTEGER(gc, 2), CONS(gc, REAL(gc, 0.2f), NIL(gc))),
- CONS(gc, REAL(gc, 2.2f), NIL(gc))
- };
- size_t n = sizeof(input) / sizeof(input[0]);
-
- for (size_t i = 0; i < n; ++i) {
- struct ParseResult result = read_expr_from_string(gc, input[i]);
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr, "Parsing failed: %s\n", result.error_message);
- });
-
-
- ASSERT_TRUE(equal(expected[i], result.expr), {
- fprintf(stderr, "Expected: ");
- print_expr_as_sexpr(stderr, expected[i]);
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Actual: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
- }
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(parse_negative_integers_test)
-{
- Gc *gc = create_gc();
- struct ParseResult result = read_expr_from_string(gc, "-12345");
-
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr, "Parsing failed: %s", result.error_message);
- });
- ASSERT_EQ(enum ExprType, EXPR_ATOM, result.expr.type, {
- fprintf(stderr, "Expected: %s\n", expr_type_as_string(_expected));
- fprintf(stderr, "Actual: %s\n", expr_type_as_string(_actual));
- });
- ASSERT_EQ(enum AtomType, ATOM_INTEGER, result.expr.atom->type, {
- fprintf(stderr, "Expected: %s\n", atom_type_as_string(_expected));
- fprintf(stderr, "Actual: %s\n", atom_type_as_string(_actual));
- });
- ASSERT_LONGINTEQ(-12345L, result.expr.atom->num);
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(read_all_exprs_from_string_empty_test)
-{
- Gc *gc = create_gc();
- struct ParseResult result = read_all_exprs_from_string(gc, "");
-
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr,
- "Parsing was unsuccessful: %s\n",
- result.error_message);
- });
-
- ASSERT_EQ(long int, 0, length_of_list(result.expr), {
- fprintf(stderr, "Expected: %ld\n", _expected);
- fprintf(stderr, "Actual: %ld\n", _actual);
- fprintf(stderr, "Expression: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(read_all_exprs_from_string_one_test)
-{
- Gc *gc = create_gc();
- struct ParseResult result = read_all_exprs_from_string(gc, "(+ 1 2)");
-
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr,
- "Parsing was unsuccessful: %s\n",
- result.error_message);
- });
-
- ASSERT_EQ(long int, 1, length_of_list(result.expr), {
- fprintf(stderr, "Expected: %ld\n", _expected);
- fprintf(stderr, "Actual: %ld\n", _actual);
- fprintf(stderr, "Expression: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(read_all_exprs_from_string_two_test)
-{
- Gc *gc = create_gc();
- struct ParseResult result = read_all_exprs_from_string(
- gc,
- "(+ 1 2) (+ 3 4)");
-
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr,
- "Parsing was unsuccessful: %s\n",
- result.error_message);
- });
-
- ASSERT_EQ(long int, 2, length_of_list(result.expr), {
- fprintf(stderr, "Expected: %ld\n", _expected);
- fprintf(stderr, "Actual: %ld\n", _actual);
- fprintf(stderr, "Expression: ");
- print_expr_as_sexpr(stderr, result.expr);
- fprintf(stderr, "\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(read_all_exprs_from_string_bad_test)
-{
- Gc *gc = create_gc();
- struct ParseResult result = read_all_exprs_from_string(
- gc,
- "(+ 1 2) + 3 4)");
-
- ASSERT_TRUE(result.is_error, {
- fprintf(stderr, "Parsing didn't fail as expected\n");
- });
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST(read_all_exprs_from_string_trailing_spaces_test)
-{
- Gc *gc = create_gc();
- const char *source_code = "5 ";
- struct ParseResult result = read_all_exprs_from_string(gc, source_code);
-
- ASSERT_FALSE(result.is_error, {
- fprintf(stderr, "Parsing failed: %s\n", result.error_message);
- fprintf(stderr, "Position: %zd\n", result.end - source_code);
- });
-
- return 0;
-}
-
-TEST_SUITE(parser_suite)
-{
- TEST_RUN(read_expr_from_file_test);
- TEST_RUN(parse_negative_integers_test);
- TEST_RUN(read_all_exprs_from_string_empty_test);
- TEST_RUN(read_all_exprs_from_string_one_test);
- TEST_RUN(read_all_exprs_from_string_two_test);
- // TODO(#467): read_all_exprs_from_string_bad_test is failing
- TEST_IGNORE(read_all_exprs_from_string_bad_test);
- TEST_RUN(read_all_exprs_from_string_trailing_spaces_test);
- TEST_RUN(parse_reals_test);
- TEST_RUN(parse_real_pair_test);
-
- return 0;
-}
-
-
-
-#endif // PARSER_SUITE_H_
+++ /dev/null
-#ifndef SCOPE_SUITE_H_
-#define SCOPE_SUITE_H_
-
-#include "test.h"
-#include "ebisp/scope.h"
-#include "ebisp/expr.h"
-
-TEST(set_scope_value_test)
-{
- Gc *gc = create_gc();
-
- struct Expr z = SYMBOL(gc, "z");
- struct Expr x = SYMBOL(gc, "x");
- struct Expr y = SYMBOL(gc, "y");
-
- struct Scope scope = {
- .expr = CONS(gc, NIL(gc), NIL(gc))
- };
-
- push_scope_frame(gc, &scope,
- list(gc, "ee", x, y),
- list(gc, "ss", "hello", "world"));
-
- set_scope_value(gc, &scope, z, STRING(gc, "foo"));
-
- ASSERT_TRUE(equal(CONS(gc, x, STRING(gc, "hello")), get_scope_value(&scope, x)),
- { fprintf(stderr, "Unexpected value of `x`\n"); });
- ASSERT_TRUE(equal(CONS(gc, y, STRING(gc, "world")), get_scope_value(&scope, y)),
- { fprintf(stderr, "Unexpected value of `y`\n"); });
- ASSERT_TRUE(equal(CONS(gc, z, STRING(gc, "foo")), get_scope_value(&scope, z)),
- { fprintf(stderr, "Unexpected value of `z`\n"); });
-
- pop_scope_frame(gc, &scope);
-
- ASSERT_TRUE(equal(NIL(gc), get_scope_value(&scope, x)),
- { fprintf(stderr, "Unexpected value of `x`\n"); });
- ASSERT_TRUE(equal(NIL(gc), get_scope_value(&scope, y)),
- { fprintf(stderr, "Unexpected value of `y`\n"); });
- ASSERT_TRUE(equal(CONS(gc, z, STRING(gc, "foo")), get_scope_value(&scope, z)),
- { fprintf(stderr, "Unexpected value of `z`\n"); });
-
-
- destroy_gc(gc);
-
- return 0;
-}
-
-TEST_SUITE(scope_suite)
-{
- TEST_RUN(set_scope_value_test);
-
- return 0;
-}
-
-#endif // SCOPE_SUITE_H_
+++ /dev/null
-#ifndef TEST_H_
-#define TEST_H_
-
-#include "math.h"
-
-#define TEST_RUN(name) \
- if (name() < 0) { \
- return -1; \
- }
-
-#define TEST_IGNORE(name) \
- (void)(name) \
-
-#define TEST(name) \
- static int name##_body(void); \
- static int name(void) { \
- printf("%s() ...", #name); \
- if (name##_body() == 0) { \
- printf(" OK\n"); \
- return 0; \
- } else { \
- printf(" FAILED\n"); \
- return -1; \
- } \
- } \
- static int name##_body(void)
-
-// TODO(#308): ASSERT_* macros evaluate expressions several times
-
-#define ASSERT_STREQN(expected, actual, n) \
- if (strncmp(expected, actual, n) != 0) { \
- fprintf(stderr, "\n%s:%d: ASSERT_STREQN: \n", \
- __FILE__, __LINE__); \
- fprintf(stderr, " Expected: "); \
- fwrite(expected, sizeof(char), n, stderr); \
- fprintf(stderr, "\n"); \
- fprintf(stderr, " Actual: "); \
- fwrite(actual, sizeof(char), n, stderr); \
- fprintf(stderr, "\n"); \
- return -1; \
- }
-
-#define ASSERT_STREQ(expected, actual) \
- if (strcmp(expected, actual) != 0) { \
- fprintf(stderr, "\n%s:%d: ASSERT_STREQ: \n", \
- __FILE__, __LINE__); \
- fprintf(stderr, " Expected: %s\n", expected); \
- fprintf(stderr, " Actual: %s\n", actual); \
- return -1; \
- }
-
-#define ASSERT_INTEQ(expected, actual) \
- if (expected != actual) { \
- fprintf(stderr, "\n%s:%d: ASSERT_INTEQ: \n", \
- __FILE__, __LINE__); \
- fprintf(stderr, " Expected: %d\n", expected); \
- fprintf(stderr, " Actual: %d\n", actual); \
- return -1; \
- }
-
-#define ASSERT_LONGINTEQ(expected, actual) \
- if (expected != actual) { \
- fprintf(stderr, "\n%s:%d: ASSERT_LONGINTEQ: \n", \
- __FILE__, __LINE__); \
- fprintf(stderr, " Expected: %ld\n", expected); \
- fprintf(stderr, " Actual: %ld\n", actual); \
- return -1; \
- }
-
-
-#define ASSERT_FLOATEQ(expected, actual, margin) \
- if (fabsf(expected - actual) > margin) { \
- fprintf(stderr, "\n%s:%d: ASSERT_FLOATEQ: \n", \
- __FILE__, __LINE__); \
- fprintf(stderr, " Expected: %f\n", expected); \
- fprintf(stderr, " Actual: %f\n", actual); \
- fprintf(stderr, " Margin: %f\n", margin); \
- return -1; \
- }
-
-#define ASSERT_EQ(type, expected, actual, handler) \
- { \
- type _expected = (expected); \
- type _actual = (actual); \
- if (_expected != _actual) { \
- fprintf(stderr, "\n%s:%d: ASSERT_EQ: \n", \
- __FILE__, __LINE__); \
- handler \
- return -1; \
- } \
- }
-
-#define ASSERT_TRUE(condition, handler) \
- if (!(condition)) { \
- fprintf(stderr, "\n%s:%d: ASSERT_TRUE: false\n", \
- __FILE__, __LINE__); \
- handler \
- return -1; \
- }
-
-#define ASSERT_FALSE(condition, handler) \
- if (condition) { \
- fprintf(stderr, "\n%s:%d: ASSERT_FALSE: false\n", \
- __FILE__, __LINE__); \
- handler \
- return -1; \
- }
-
-#define TEST_SUITE(name) \
- static int name##_body(void); \
- static int name(void) { \
- if (name##_body() < 0) { \
- return -1; \
- } \
- return 0; \
- } \
- static int name##_body(void)
-
-#define TEST_MAIN() \
- static int main_body(void); \
- int main(void) { \
- if (main_body() < 0) { \
- return -1; \
- } \
- return 0; \
- } \
- static int main_body(void)
-
-#endif // TEST_H_
+++ /dev/null
-#ifndef TOKENIZER_SUITE_H_
-#define TOKENIZER_SUITE_H_
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "test.h"
-#include "ebisp/tokenizer.h"
-
-TEST(tokenizer_integer_list_test)
-{
- struct Token token = next_token("(1 2 3)");
- ASSERT_STREQN("(", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN("1", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN("2", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN("3", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN(")", token.begin, (size_t) (token.end - token.begin));
-
- return 0;
-}
-
-TEST(tokenizer_string_list_test)
-{
- struct Token token = next_token("(\"foo\" \"bar\" \"baz\")");
- ASSERT_STREQN("(", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN("\"foo\"", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN("\"bar\"", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN("\"baz\"", token.begin, (size_t) (token.end - token.begin));
-
- token = next_token(token.end);
- ASSERT_STREQN(")", token.begin, (size_t) (token.end - token.begin));
-
- return 0;
-}
-
-TEST_SUITE(tokenizer_suite)
-{
- TEST_RUN(tokenizer_integer_list_test);
- TEST_RUN(tokenizer_string_list_test);
- return 0;
-}
-
-#endif // TOKENIZER_SUITE_H_