From ce5708af981fa09c2f26eebf2f93b41ed41e8c47 Mon Sep 17 00:00:00 2001 From: bakpakin Date: Mon, 29 Jan 2018 15:46:26 -0500 Subject: [PATCH] Switch over to Cmake fully. --- .travis.yml | 7 +- CMakeLists.txt | 48 +++++++++--- Makefile | 104 -------------------------- README.md | 33 +++++--- src/assembler/asm.c | 8 +- src/compiler/compile.c | 3 +- src/compiler/context.c | 10 +-- src/core/bytecode.c | 4 +- src/include/dst/dstasm.h | 3 +- src/include/dst/dstcompile.h | 11 ++- src/include/dst/dstopcodes.h | 5 +- src/include/dst/dstparse.h | 3 +- src/include/headerlibs/strbinsearch.h | 3 +- src/mainclient/main.c | 5 +- src/parser/parse.c | 6 +- test/boot.dst | 76 +++++++++++++++++++ test/example.dsts | 67 ----------------- test/hello.dst | 1 - test/minimal.dsts | 26 ------- test/repl.dst | 14 ---- test/scratch.dst | 34 --------- test/suite0.dst | 2 +- test/suite1.dst | 24 ++++++ 23 files changed, 196 insertions(+), 301 deletions(-) delete mode 100644 Makefile create mode 100644 test/boot.dst delete mode 100644 test/example.dsts delete mode 100644 test/hello.dst delete mode 100644 test/minimal.dsts delete mode 100644 test/repl.dst delete mode 100644 test/scratch.dst create mode 100644 test/suite1.dst diff --git a/.travis.yml b/.travis.yml index c2be36b3..792a00c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,11 @@ language: c -script: make test +script: + - mkdir -p build + - cd build + - cmake .. + - make + - make test compiler: - clang diff --git a/CMakeLists.txt b/CMakeLists.txt index 337c16d2..a9ae0dd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,18 +18,13 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -cmake_minimum_required(VERSION 3.9) +cmake_minimum_required(VERSION 3.7) project(dst) # Set Some Variables set(TARGET_NAME ${PROJECT_NAME}) -if (CMAKE_VERSION VERSION_LESS "3.1") - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - set (CMAKE_C_FLAGS "--std=gnu99 ${CMAKE_C_FLAGS}") - endif () -else () - set (CMAKE_C_STANDARD 99) -endif () +set (CMAKE_C_STANDARD 99) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") include_directories(src/include) @@ -86,7 +81,7 @@ set(TESTLIB_SOURCES src/testlib/testlib.c ) -set(SOURCES +set(REPL_SOURCES ${ASSEMBLER_SOURCES} ${COMPILER_SOURCES} ${CORE_SOURCES} @@ -94,6 +89,39 @@ ${MAINCLIENT_SOURCES} ${PARSER_SOURCES} ) +# Set Public headers +set(DST_PUBLIC_HEADERS +src/include/dst/dst.h +src/include/dst/dstasm.h +src/include/dst/dstcompile.h +src/include/dst/dstconfig.h +src/include/dst/dstopcodes.h +src/include/dst/dstparse.h +src/include/dst/dststate.h +src/include/dst/dststl.h +src/include/dst/dsttypes.h +) + # Build the executable -add_executable(${TARGET_NAME} ${SOURCES}) +add_executable(${TARGET_NAME} ${REPL_SOURCES}) target_link_libraries(${TARGET_NAME} m dl) +set_target_properties(${TARGET_NAME} PROPERTIES PUBLIC_HEADER "${DST_PUBLIC_HEADERS}") + +# Install +install(TARGETS ${TARGET_NAME} + LIBRARY DESTINATION "lib" + RUNTIME DESTINATION "bin" + PUBLIC_HEADER DESTINATION "include/dst" +) + +# Add some test scripts +enable_testing() +add_test(suite0 ${TARGET_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/test/suite0.dst) +add_test(suite1 ${TARGET_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/test/suite1.dst) + +# Add convenience script to run repl +add_custom_target(run + COMMAND ${TARGET_NAME} + DEPENDS ${TARGET_NAME} + WORKING_DIRECTORY ${CMAKE_PROJECT_DIR} +) diff --git a/Makefile b/Makefile deleted file mode 100644 index f43371a2..00000000 --- a/Makefile +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2017 Calvin Rose -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -################################ -##### Set global variables ##### -################################ - -PREFIX?=/usr/local -BINDIR=$(PREFIX)/bin - -CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -g -CLIBS=-lm -ldl -PREFIX=/usr/local -DST_TARGET=dst -DEBUGGER=lldb - -DST_C_LIBS=$(addprefix libs/,testlib.so) - -DST_HEADERS=$(sort $(wildcard src/include/dst/*.h)) -DST_LIBHEADERS=$(sort $(wildcard src/include/headerlibs/*.h)) -DST_ALL_HEADERS=$(DST_HEADERS) $(DST_LIB_HEADERS) - -DST_ASM_SOURCES=$(sort $(wildcard src/assembler/*.c)) -DST_COMPILER_SOURCES=$(sort $(wildcard src/compiler/*.c)) -DST_CONTEXT_SOURCES=$(sort $(wildcard src/context/*.c)) -DST_CORE_SOURCES=$(sort $(wildcard src/core/*.c)) -DST_MAINCLIENT_SOURCES=$(sort $(wildcard src/mainclient/*.c)) -DST_PARSER_SOURCES=$(sort $(wildcard src/parser/*.c)) - -all: $(DST_TARGET) - -######################################## -##### The main interpreter program ##### -######################################## - -DST_ALL_SOURCES=$(DST_ASM_SOURCES) \ - $(DST_COMPILER_SOURCES) \ - $(DST_CONTEXT_SOURCES) \ - $(DST_CORE_SOURCES) \ - $(DST_MAINCLIENT_SOURCES) \ - $(DST_PARSER_SOURCES) - -$(DST_TARGET): $(DST_ALL_SOURCES) $(DST_ALL_HEADERS) - $(CC) $(CFLAGS) -o $(DST_TARGET) $(DST_ALL_SOURCES) $(CLIBS) - -####################### -##### C Libraries ##### -####################### - -%.so: %.c $(DST_HEADERS) - $(CC) $(CFLAGS) -DDST_LIB -shared -undefined dynamic_lookup -o $@ $< - -################### -##### Testing ##### -################### - -repl: $(DST_TARGET) - @ ./$(DST_TARGET) - -debug: $(DST_TARGET) - @ $(DEBUGGER) ./$(DST_TARGET) - -valgrind: $(DST_TARGET) - @ valgrind --leak-check=full -v ./$(DST_TARGET) - -test: $(DST_TARGET) - @ ./$(DST_TARGET) --gcinterval=0x10000 test/suite0.dst - -valtest: $(DST_TARGET) - valgrind --leak-check=full -v ./$(DST_TARGET) dsttests/basic.dst - -################# -##### Other ##### -################# - -clean: - rm $(DST_TARGET) || true - rm src/**/*.o || true - rm vgcore.* || true - -install: $(DST_TARGET) - cp $(DST_TARGET) $(BINDIR)/dst - -uninstall: - rm $(BINDIR)/dst - -.PHONY: clean install repl debug valgrind test valtest install uninstall diff --git a/README.md b/README.md index d776ae7f..4a0a385a 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,11 @@ [![Build Status](https://travis-ci.org/bakpakin/dst.svg?branch=master)](https://travis-ci.org/bakpakin/dst) -dst is a functional programming language and vm. It is a variant of -Lisp with several native useful datatypes. Some of the more interesting and -useful features are first class functions and closures, immutable and mutable -hashtables, arrays, and bytebuffers, macros, tail-call optimization, -and continuations. The runtime and -compiler are written in C99. +dst is a functional programming language and vm. The language is a lisp that replaces +the list with other data structures that have better realworld characteristics and performance. +The language can also easily bridge to native code, and +native useful datatypes. The bytecode vm is a register based vm loosely inspired +by the LuaJIT bytecode format. There is a repl for trying out the language, as well as the ability to run script files. This client program is separate from the core runtime, so @@ -22,20 +21,32 @@ dst could be embedded into other programs. * Mutable and immutable arrays (array/tuple) * Mutable and immutable hashtables (table/struct) * Mutable and immutable strings (buffer/string) +* Lisp Macros * Byte code interpreter with an assembly interface, as well as bytecode verification -* Proper tail calls for functional code +* Proper tail calls. * Direct interop with C via abstract types and C functions * Dynamically load C libraries -* REPL (read eval print loop) +* REPL ## Compiling and Running -To build the runtime and run test, run +Dst is built using CMake. There used to be a hand-written Makefile, but in the interest of +easier Windows support I have switched to CMake. + +On a posix system using make, compiling and running is as follows (this is the same as +most CMake based projects). + +### Build ```sh +cd somewhere/my/projects/dst +mkdir -p build +cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make make test ``` -A repl can also be run with +The repl can also be run with the CMake run target. ```sh -make repl +make run ``` diff --git a/src/assembler/asm.c b/src/assembler/asm.c index 0a702517..08c7401d 100644 --- a/src/assembler/asm.c +++ b/src/assembler/asm.c @@ -46,7 +46,7 @@ typedef struct DstInstructionDef DstInstructionDef; struct DstInstructionDef { const char *name; - DstOpCode opcode; + enum DstOpCode opcode; }; /* Hold all state needed during assembly */ @@ -216,7 +216,7 @@ static int32_t dst_asm_addenv(DstAssembler *a, Dst envname) { * integer. This integer will need to be bounds checked. */ static int32_t doarg_1( DstAssembler *a, - DstOpArgType argtype, + enum DstOpArgType argtype, Dst x) { int32_t ret = -1; DstTable *c; @@ -311,7 +311,7 @@ static int32_t doarg_1( * try to convert arguments to bit patterns */ static uint32_t doarg( DstAssembler *a, - DstOpArgType argtype, + enum DstOpArgType argtype, int nth, int nbytes, int hassign, @@ -336,7 +336,7 @@ static uint32_t read_instruction( const DstInstructionDef *idef, const Dst *argt) { uint32_t instr = idef->opcode; - DstInstructionType type = dst_instructions[idef->opcode]; + enum DstInstructionType type = dst_instructions[idef->opcode]; switch (type) { case DIT_0: { diff --git a/src/compiler/compile.c b/src/compiler/compile.c index 93182020..1a0c26e6 100644 --- a/src/compiler/compile.c +++ b/src/compiler/compile.c @@ -241,7 +241,8 @@ DstSlot dstc_resolve( if (scope->flags & DST_SCOPE_UNUSED) unused = 1; len = dst_v_count(scope->syms); - for (i = 0; i < len; i++) { + /* Search in reverse order */ + for (i = len - 1; i >= 0; i--) { pair = scope->syms + i; if (pair->sym == sym) { ret = pair->slot; diff --git a/src/compiler/context.c b/src/compiler/context.c index d8763434..4e900957 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -27,7 +27,7 @@ #define CHUNKSIZE 1024 /* Read input for a repl */ -static int replread(DstContext *c, DstParserStatus status) { +static int replread(DstContext *c, enum DstParserStatus status) { if (status == DST_PARSE_PENDING) printf(">> "); else @@ -53,7 +53,7 @@ static void replonvalue(DstContext *c, Dst value) { } /* Handle errors on repl */ -static void simpleerror(DstContext *c, DstContextErrorType type, Dst err, size_t start, size_t end) { +static void simpleerror(DstContext *c, enum DstContextErrorType type, Dst err, size_t start, size_t end) { const char *errtype; (void) c; (void) start; @@ -76,7 +76,7 @@ static void filedeinit(DstContext *c) { fclose((FILE *) (c->user)); } -static int fileread(DstContext *c, DstParserStatus status) { +static int fileread(DstContext *c, enum DstParserStatus status) { size_t nread; FILE *f = (FILE *) c->user; (void) status; @@ -132,7 +132,7 @@ int dst_context_file(DstContext *c, DstTable *env, const char *path) { /* Do something on an error. Return flags to or with current flags. */ static int doerror( DstContext *c, - DstContextErrorType type, + enum DstContextErrorType type, Dst err, int32_t bstart, int32_t bend) { @@ -150,7 +150,7 @@ int dst_context_run(DstContext *c, int flags) { int done = 0; int errflags = 0; DstParser parser; - DstParserStatus status; + enum DstParserStatus status; dst_parser_init(&parser, flags); while (!done) { int bufferdone = 0; diff --git a/src/core/bytecode.c b/src/core/bytecode.c index d7dc4052..df8bb577 100644 --- a/src/core/bytecode.c +++ b/src/core/bytecode.c @@ -25,7 +25,7 @@ #include "gc.h" /* Look up table for instructions */ -DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT] = { +enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT] = { DIT_0, /* DOP_NOOP, */ DIT_S, /* DOP_ERROR, */ DIT_ST, /* DOP_TYPECHECK, */ @@ -106,7 +106,7 @@ int32_t dst_verify(DstFuncDef *def) { if ((instr & 0xFF) >= DOP_INSTRUCTION_COUNT) { return 3; } - DstInstructionType type = dst_instructions[instr & 0xFF]; + enum DstInstructionType type = dst_instructions[instr & 0xFF]; switch (type) { case DIT_0: continue; diff --git a/src/include/dst/dstasm.h b/src/include/dst/dstasm.h index e5e12e51..4372e660 100644 --- a/src/include/dst/dstasm.h +++ b/src/include/dst/dstasm.h @@ -30,7 +30,6 @@ extern "C" { #include "dsttypes.h" /* Assembly */ -typedef enum DstAssembleStatus DstAssembleStatus; typedef struct DstAssembleResult DstAssembleResult; typedef struct DstAssembleOptions DstAssembleOptions; enum DstAssembleStatus { @@ -40,7 +39,7 @@ enum DstAssembleStatus { struct DstAssembleResult { DstFuncDef *funcdef; const uint8_t *error; - DstAssembleStatus status; + enum DstAssembleStatus status; }; DstAssembleResult dst_asm(Dst source, int flags); Dst dst_disasm(DstFuncDef *def); diff --git a/src/include/dst/dstcompile.h b/src/include/dst/dstcompile.h index 8dc401c3..a90f0683 100644 --- a/src/include/dst/dstcompile.h +++ b/src/include/dst/dstcompile.h @@ -30,7 +30,6 @@ extern "C" { #include "dsttypes.h" #include "dstparse.h" -typedef enum DstCompileStatus DstCompileStatus; typedef struct DstCompileOptions DstCompileOptions; typedef struct DstCompileResult DstCompileResult; enum DstCompileStatus { @@ -38,7 +37,7 @@ enum DstCompileStatus { DST_COMPILE_ERROR }; struct DstCompileResult { - DstCompileStatus status; + enum DstCompileStatus status; DstFuncDef *funcdef; const uint8_t *error; int32_t error_start; @@ -57,11 +56,11 @@ int dst_context_file(DstContext *c, DstTable *env, const char *path); int dst_context_run(DstContext *c, int flags); /* Parse structs */ -typedef enum { +enum DstContextErrorType { DST_CONTEXT_ERROR_PARSE, DST_CONTEXT_ERROR_COMPILE, DST_CONTEXT_ERROR_RUNTIME -} DstContextErrorType; +}; /* Evaluation context. Encapsulates parsing and compiling for easier integration * with client programs. */ @@ -71,8 +70,8 @@ struct DstContext { void *user; int32_t index; - int (*read_chunk)(DstContext *self, DstParserStatus status); - void (*on_error)(DstContext *self, DstContextErrorType type, Dst err, size_t start, size_t end); + int (*read_chunk)(DstContext *self, enum DstParserStatus status); + void (*on_error)(DstContext *self, enum DstContextErrorType type, Dst err, size_t start, size_t end); void (*on_value)(DstContext *self, Dst value); void (*deinit)(DstContext *self); }; diff --git a/src/include/dst/dstopcodes.h b/src/include/dst/dstopcodes.h index ac86fb87..1a68794d 100644 --- a/src/include/dst/dstopcodes.h +++ b/src/include/dst/dstopcodes.h @@ -28,7 +28,6 @@ extern "C" { #endif /* Bytecode op argument types */ -typedef enum DstOpArgType DstOpArgType; enum DstOpArgType { DST_OAT_SLOT, DST_OAT_ENVIRONMENT, @@ -41,7 +40,6 @@ enum DstOpArgType { }; /* Various types of instructions */ -typedef enum DstInstructionType DstInstructionType; enum DstInstructionType { DIT_0, /* No args */ DIT_S, /* Slot(3) */ @@ -59,7 +57,6 @@ enum DstInstructionType { DIT_SC /* Slot(1), Constant(2) */ }; -typedef enum DstOpCode DstOpCode; enum DstOpCode { DOP_NOOP, DOP_ERROR, @@ -125,7 +122,7 @@ enum DstOpCode { }; /* Info about all instructions */ -extern DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT]; +extern enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT]; #ifdef __cplusplus } diff --git a/src/include/dst/dstparse.h b/src/include/dst/dstparse.h index ab3d904c..5c9883d5 100644 --- a/src/include/dst/dstparse.h +++ b/src/include/dst/dstparse.h @@ -29,7 +29,6 @@ extern "C" { #include "dsttypes.h" -typedef enum DstParserStatus DstParserStatus; typedef struct DstParseState DstParseState; typedef struct DstParser DstParser; @@ -60,7 +59,7 @@ struct DstParser { void dst_parser_init(DstParser *parser, int flags); void dst_parser_deinit(DstParser *parser); int dst_parser_consume(DstParser *parser, uint8_t c); -DstParserStatus dst_parser_status(DstParser *parser); +enum DstParserStatus dst_parser_status(DstParser *parser); Dst dst_parser_produce(DstParser *parser); const char *dst_parser_error(DstParser *parser); int dst_parse_cfun(DstArgs args); diff --git a/src/include/headerlibs/strbinsearch.h b/src/include/headerlibs/strbinsearch.h index de14d5f9..cc6e2203 100644 --- a/src/include/headerlibs/strbinsearch.h +++ b/src/include/headerlibs/strbinsearch.h @@ -33,9 +33,10 @@ static const void *dst_strbinsearch( const uint8_t *key) { size_t low = 0; size_t hi = tabcount; + const char *t = (const char *)tab; while (low < hi) { size_t mid = low + ((hi - low) / 2); - const char **item = (const char **)(tab + mid * itemsize); + const char **item = (const char **)(t + mid * itemsize); const char *name = *item; int comp = dst_cstrcmp(key, name); if (comp < 0) { diff --git a/src/mainclient/main.c b/src/mainclient/main.c index d917f852..d6cc6922 100644 --- a/src/mainclient/main.c +++ b/src/mainclient/main.c @@ -79,7 +79,7 @@ int main(int argc, char **argv) { } else { flags |= DST_CLIENT_UNKNOWN; } - } else { + } else if (*arg) { /* Flag */ const char *c = arg; while (*(++c)) { @@ -139,9 +139,10 @@ int main(int argc, char **argv) { fileRead = 1; if (dst_context_file(&ctxt, env, arg)) { printf("file %s not found\n", arg); + status |= 2; continue; } - status = dst_context_run(&ctxt, DST_PARSEFLAG_SOURCEMAP); + status |= dst_context_run(&ctxt, DST_PARSEFLAG_SOURCEMAP); } } diff --git a/src/parser/parse.c b/src/parser/parse.c index de6d1b4c..8c2f8810 100644 --- a/src/parser/parse.c +++ b/src/parser/parse.c @@ -464,7 +464,7 @@ int dst_parser_consume(DstParser *parser, uint8_t c) { return 1; } -DstParserStatus dst_parser_status(DstParser *parser) { +enum DstParserStatus dst_parser_status(DstParser *parser) { if (parser->error) return DST_PARSE_ERROR; if (dst_v_count(parser->states) > 1) return DST_PARSE_PENDING; if (dst_v_count(parser->argstack)) return DST_PARSE_FULL; @@ -472,7 +472,7 @@ DstParserStatus dst_parser_status(DstParser *parser) { } const char *dst_parser_error(DstParser *parser) { - DstParserStatus status = dst_parser_status(parser); + enum DstParserStatus status = dst_parser_status(parser); if (status == DST_PARSE_ERROR) { const char *e = parser->error; dst_v_empty(parser->argstack); @@ -487,7 +487,7 @@ const char *dst_parser_error(DstParser *parser) { Dst dst_parser_produce(DstParser *parser) { Dst ret; int32_t i; - DstParserStatus status = dst_parser_status(parser); + enum DstParserStatus status = dst_parser_status(parser); if (status != DST_PARSE_FULL) return dst_wrap_nil(); ret = parser->argstack[0]; for (i = 1; i < dst_v_count(parser->argstack); i++) { diff --git a/test/boot.dst b/test/boot.dst new file mode 100644 index 00000000..c16b1769 --- /dev/null +++ b/test/boot.dst @@ -0,0 +1,76 @@ +# Copyright (c) 2017 Calvin Rose +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +# Bootstrap the language + +(def defmacro macro (fn [name & more] + (tuple 'def name 'macro (tuple-prepend (tuple-prepend more name) 'fn)))) +(defmacro defn + [name & more] + (tuple 'def name + (tuple-prepend (tuple-prepend more name) 'fn))) + +(defmacro when [cond & body] (tuple 'if cond (tuple-prepend body 'do))) + +(defn array-seq [x] + (def len (length x)) + (var i 0) + { + :more (fn [] (< i len)) + :next (fn [] + (def ret (get x i)) + (varset! i (+ i 1)) + ret) + }) + +(def seqs { + :array array-seq + :tuple array-seq + :struct (fn [x] x)}) + +(defn seq [x] + (def makeseq (get seqs (type x))) + (if makeseq (makeseq x) (error "expected sequence"))) + +(defn range [top] + (var i 0) + { + :more (fn [] (< i top)) + :next (fn [] + (def ret i) + (varset! i (+ i 1)) + i) + }) + +(defn doseq [s f] + (def s (seq s)) + (def more? (get s :more)) + (def getnext (get s :next)) + (while (more?) + (f (getnext)))) + +(defn map [f s] + (def s (seq s)) + (def more (get s :more)) + (def getnext (get s :next)) + { + :more more + :next (f (getnext)) + }) diff --git a/test/example.dsts b/test/example.dsts deleted file mode 100644 index ed3873ce..00000000 --- a/test/example.dsts +++ /dev/null @@ -1,67 +0,0 @@ -# A .dsts file will contain VM, assembly for a dst function. This includes -# associated constants and what not. The assembler should be able to -# simply construct a FuncDef from this file. This file is also parsed -# in the same markup as dst itself (extended S expressions) -{ - arity 3 - source "source file path" - vararg false -# Name for reference by nested funcdefs - name outerfunc -# Contains the bytecode for this function. This can be assembly -# instructions or integers. Assembly will be converted to integer bytecodes immediately. - bytecode [ - (load-constant 0 bork) - (load-constant 1 bip) - (add 0 0 1) - (add-immediate 0 0 127) - (push3 0 0 0) - (push3 0 0 0) - (push3 0 0 0) - (syscall 1 0) - (return 0) - ] -# A source map is optional. The sourcemap corresponds with the byte code. -# Each instruction has two source map entries, offset start and offset end. -# map [ -# 1 -# 2 -# 3 -# 10 -# 15 -# 39 -# 90 -# 134 -# ... -# ] -# -# The number of slots available for the function. -# Slots can be named as well for convenience. - slots [ - x - y - z - ] -# Captured outer environments that are referenced - captures [ ] -# Constants are an array or tuple. For named constants, use a tuple that begins with let -# For a literal tuple, use (quote tuple), or 'tuple. Without names, constants must be indexed -# from their number -# Literal FuncEnvs and Functions may be possible later - constants [ - :hello - (def bork 123) - (def bip 456) - '(1 2 3) - (def atuple (1 2 3)) - (567) - ] -# Arbitrary meta data can be added to the source - my-meta-2 @{ - 1 2 3 4 - } - my-meta { - 1 2 3 4 5 6 7 8 9 0 11 12 13 14 - } -} - diff --git a/test/hello.dst b/test/hello.dst deleted file mode 100644 index e83d7385..00000000 --- a/test/hello.dst +++ /dev/null @@ -1 +0,0 @@ -(print "Hello, World!") diff --git a/test/minimal.dsts b/test/minimal.dsts deleted file mode 100644 index 4c7d8d6c..00000000 --- a/test/minimal.dsts +++ /dev/null @@ -1,26 +0,0 @@ -# A fairly minimal example of a dst assembly file -{ - bytecode [ - (load-integer 0 15) - (load-integer 1 0) - (load-constant 3 lookup) - - :label - (equals 2 1 0) - (jump-if 2 :done) - (add-immediate 0 0 -1) - (get 2 3 0) - (push 2) - (syscall 2 0) - (jump :label) - - :done - (return-nil) - - :extra - (push 2) - ] - constants [ - (def lookup "0123456789abcdef") - ] -} diff --git a/test/repl.dst b/test/repl.dst deleted file mode 100644 index f8e29998..00000000 --- a/test/repl.dst +++ /dev/null @@ -1,14 +0,0 @@ -# Bootstrap the language - -# Helper for macro expansion -(def macroexpand (fn recur [x] - (def y (ast-unwrap x)) - (if (= (type y) :tuple) - (if (> (length y) 0) - (do - (def first (get y 0)) - (def rest (array-slice y 1)) - (def macro (get _env first)) - (if macro (recur (apply macro rest)) x)) - x) - x))) diff --git a/test/scratch.dst b/test/scratch.dst deleted file mode 100644 index d54bf37d..00000000 --- a/test/scratch.dst +++ /dev/null @@ -1,34 +0,0 @@ -(def mapnil - " (mapnil f a) - Map a function over a tuple or array and return nil." - (fn [f t] - (var i 0) - (def len (length t)) - (while (< i len) - (f (get t i)) - (varset! i (+ i 1))))) - -(def mapt - " (mapt f t) - Map a function over a tuple or array and produce a new tuple." - (fn [f t] - (var i 0) - (def len (length t)) - (def accum []) - (while (< i len) - (array-push accum (f (get t i))) - (varset! i (+ i 1))) - (apply tuple accum))) - -(def mapa - " (mapa f a) - Map a function over a tuple or array and produce a new array." - (fn [f t] - (var i 0) - (def len (length t)) - (def accum []) - (while (< i len) - (array-push accum (f (get t i))) - (varset! i (+ i 1))) - accum)) - diff --git a/test/suite0.dst b/test/suite0.dst index d9c796c8..eaf6d823 100644 --- a/test/suite0.dst +++ b/test/suite0.dst @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -(print "\nRunning basic tests...\n") +(print "\nRunning Suite 0 tests...\n") (var num-tests-passed 0) (var num-tests-run 0) diff --git a/test/suite1.dst b/test/suite1.dst new file mode 100644 index 00000000..ec44c07b --- /dev/null +++ b/test/suite1.dst @@ -0,0 +1,24 @@ +# Copyright (c) 2017 Calvin Rose +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +(print "\nRunning Suite 1 Tests...\n") + +(if (not= 400.0 (sqrt 160000)) (error "sqrt(160000)=400")) +(if (not= (real 400) (sqrt 160000)) (error "sqrt(160000)=400"))