1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-30 20:09:54 +00:00

Switch over to Cmake fully.

This commit is contained in:
bakpakin 2018-01-29 15:46:26 -05:00
parent b305a7c9bb
commit ce5708af98
23 changed files with 196 additions and 301 deletions

View File

@ -1,6 +1,11 @@
language: c
script: make test
script:
- mkdir -p build
- cd build
- cmake ..
- make
- make test
compiler:
- clang

View File

@ -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
View File

@ -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

View File

@ -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
```

View File

@ -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:
{

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
};

View File

@ -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
}

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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
View 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))
})

View File

@ -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
}
}

View File

@ -1 +0,0 @@
(print "Hello, World!")

View File

@ -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")
]
}

View File

@ -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)))

View File

@ -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))

View File

@ -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
View 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"))