mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 02:59:54 +00:00
Switch over to Cmake fully.
This commit is contained in:
parent
b305a7c9bb
commit
ce5708af98
@ -1,6 +1,11 @@
|
||||
language: c
|
||||
|
||||
script: make test
|
||||
script:
|
||||
- mkdir -p build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make
|
||||
- make test
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
|
@ -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}
|
||||
)
|
||||
|
104
Makefile
104
Makefile
@ -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
|
33
README.md
33
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
|
||||
```
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
76
test/boot.dst
Normal file
76
test/boot.dst
Normal file
@ -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))
|
||||
})
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
(print "Hello, World!")
|
@ -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")
|
||||
]
|
||||
}
|
@ -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)))
|
@ -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))
|
||||
|
@ -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)
|
||||
|
24
test/suite1.dst
Normal file
24
test/suite1.dst
Normal file
@ -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"))
|
Loading…
Reference in New Issue
Block a user