From e8dfe673f25aa3670e61ef2646302bfd6d133252 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 15 Mar 2018 23:27:44 -0400 Subject: [PATCH] Update sourcemapping structure. Add seqs example file. --- examples/lazyseqs.dst | 82 ++++++++++++++++++++++++++++++++++++++ src/assembler/asm.c | 17 ++++---- src/compiler/boot.dst | 10 +++++ src/compiler/compile.c | 14 ++++--- src/include/dst/dsttypes.h | 8 +++- 5 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 examples/lazyseqs.dst diff --git a/examples/lazyseqs.dst b/examples/lazyseqs.dst new file mode 100644 index 00000000..fa621802 --- /dev/null +++ b/examples/lazyseqs.dst @@ -0,0 +1,82 @@ +# An example implementation of functional, lazy +# sequences, like in clojure. +# Use with (import "./path/to/this/file" :prefix "seq/") + +(defn- mem0 [f] + "Memoize a 0 arity function." + (var state nil) + (var loaded nil) + (fn [] + (if loaded + state + (do + (def n (f)) + (varset! state n) + (varset! loaded true) + n)))) + +(defmacro delay + "Macro for lazy evaluation" + [x] (tuple mem0 (tuple 'fn [] x))) + +# Use tuples instead of structs to save memory +(def HEAD :private 0) +(def TAIL :private 1) + +(defn empty-seq + "The empty sequence." + [] nil) + +(defn cons + "Create a new sequence by prepending a value to the original sequence." + [h t] + (delay (tuple h t))) + +(defn empty? + "Check if a sequence is empty." + [s] + (not (s))) + +(defn head + "Get the next value of the sequence." + [s] + (get (s) HEAD)) + +(defn tail + "Get the rest of a sequence" + [s] + (get (s) TAIL)) + +(defn range + "Return a sequence of integers [start, end)." + [start end] + (if (< start end) + (cons start (range (+ 1 start) end)) + empty-seq)) + +(defn map + "Return a sequence that is the result of apply f to each value in s." + [f s] + (if (s) (cons (f (head s)) (map f (tail s))) empty-seq)) + +(defn realize + "Force evaluation of a lazy sequence." + [s] + (when (s) (realize (tail s)))) + +(defn realize-map [f s] + "Evaluate f on each member of the sequence. Forces evaluation." + (when (s) (f (head s)) (realize-map f (tail s)))) + +(defn drop + "Ignores the first n values of the sequence and returns the rest." + [n s] + (if (s) (if (zero? n) s (drop (- n 1) (tail s))) empty-seq)) + +(defn take + "Returns at most the first n values of s." + [n s] + (if (and (s) (pos? n)) + (cons (head s) (take (- n 1) (tail s))) + empty-seq)) + diff --git a/src/assembler/asm.c b/src/assembler/asm.c index 44bf06d4..74c5088f 100644 --- a/src/assembler/asm.c +++ b/src/assembler/asm.c @@ -658,10 +658,11 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { x = dst_get(s, dst_csymbolv("sourcemap")); if (dst_seq_view(x, &arr, &count)) { dst_asm_assert(&a, count == def->bytecode_length, "sourcemap must have the same length as the bytecode"); - def->sourcemap = malloc(sizeof(int32_t) * 2 * count); + def->sourcemap = malloc(sizeof(DstSourceMapping) * count); for (i = 0; i < count; i++) { const Dst *tup; Dst entry = arr[i]; + DstSourceMapping mapping; if (!dst_checktype(entry, DST_TUPLE)) { dst_asm_error(&a, "expected tuple"); } @@ -672,8 +673,9 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { if (!dst_checktype(tup[1], DST_INTEGER)) { dst_asm_error(&a, "expected integer"); } - def->sourcemap[2*i] = dst_unwrap_integer(tup[0]); - def->sourcemap[2*i+1] = dst_unwrap_integer(tup[1]); + mapping.start = dst_unwrap_integer(tup[0]); + mapping.end = dst_unwrap_integer(tup[1]); + def->sourcemap[i] = mapping; } } @@ -831,11 +833,12 @@ Dst dst_disasm(DstFuncDef *def) { /* Add source map */ if (NULL != def->sourcemap) { DstArray *sourcemap = dst_array(def->bytecode_length); - for (i = 0; i < def->bytecode_length * 2; i += 2) { + for (i = 0; i < def->bytecode_length; i++) { Dst *t = dst_tuple_begin(2); - t[0] = dst_wrap_integer(def->sourcemap[i]); - t[1] = dst_wrap_integer(def->sourcemap[i + 1]); - sourcemap->data[i / 2] = dst_wrap_tuple(dst_tuple_end(t)); + DstSourceMapping mapping = def->sourcemap[i]; + t[0] = dst_wrap_integer(mapping.start); + t[1] = dst_wrap_integer(mapping.end); + sourcemap->data[i] = dst_wrap_tuple(dst_tuple_end(t)); } sourcemap->count = def->bytecode_length; dst_table_put(ret, dst_csymbolv("sourcemap"), dst_wrap_array(sourcemap)); diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index 67e96b9e..febe1572 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -1,3 +1,5 @@ +# Bootstrap the dst environment +# Copyright 2018 (C) Calvin Rose # Capture the current env (var *env* @@ -26,6 +28,12 @@ (def args (array-concat [] name :macro more)) (apply defn* args)))) +(defmacro defmacro- + "Define a private macro that will not be exported." + [name & more] + (apply tuple (array-concat + ['defmacro name :private] more))) + (defmacro defn- "Define a private function that will not be exported." [name & more] @@ -36,6 +44,8 @@ (defn odd? [x] (== 1 (% x 2))) (defn nil? [x] (= x nil)) (defn zero? [x] (== x 0)) +(defn pos? [x] (> x 0)) +(defn neg? [x] (< x 0)) (defn one? [x] (== x 1)) (defn inc [x] (+ x 1)) (defn dec [x] (- x 1)) diff --git a/src/compiler/compile.c b/src/compiler/compile.c index 63d18436..1c4c5d2d 100644 --- a/src/compiler/compile.c +++ b/src/compiler/compile.c @@ -903,20 +903,22 @@ DstFuncDef *dstc_pop_funcdef(DstCompiler *c) { dst_v__cnt(c->buffer) = scope.bytecode_start; if (NULL != c->mapbuffer) { int32_t i; - size_t s = sizeof(int32_t) * 2 * dst_v_count(c->mapbuffer); - def->sourcemap = malloc(2 * s); + size_t s = sizeof(DstSourceMapping) * dst_v_count(c->mapbuffer); + def->sourcemap = malloc(s); if (NULL == def->sourcemap) { DST_OUT_OF_MEMORY; } for (i = 0; i < dst_v_count(c->mapbuffer); i++) { DstAst *a = c->mapbuffer[i]; + DstSourceMapping mapping; if (a) { - def->sourcemap[2 * i] = a->source_start; - def->sourcemap[2 * i + 1] = a->source_end; + mapping.start = a->source_start; + mapping.end = a->source_end; } else { - def->sourcemap[2 * i] = -1; - def->sourcemap[2 * i + 1] = -1; + mapping.start = -1; + mapping.end = -1; } + def->sourcemap[i] = mapping; } dst_v__cnt(c->mapbuffer) = scope.bytecode_start; } diff --git a/src/include/dst/dsttypes.h b/src/include/dst/dsttypes.h index 1ed68d3c..53a70ff8 100644 --- a/src/include/dst/dsttypes.h +++ b/src/include/dst/dsttypes.h @@ -52,6 +52,7 @@ typedef struct DstAbstractType DstAbstractType; typedef struct DstArgs DstArgs; typedef struct DstAst DstAst; typedef struct DstReg DstReg; +typedef struct DstSourceMapping DstSourceMapping; typedef int (*DstCFunction)(DstArgs args); /* Basic types for all Dst Values */ @@ -378,6 +379,11 @@ struct DstKV { #define DST_FUNCDEF_FLAG_VARARG 1 #define DST_FUNCDEF_FLAG_NEEDSENV 4 +struct DstSourceMapping { + int32_t start; + int32_t end; +}; + /* A function definition. Contains information needed to instantiate closures. */ struct DstFuncDef { int32_t *environments; /* Which environments to capture from parent. */ @@ -386,7 +392,7 @@ struct DstFuncDef { uint32_t *bytecode; /* Various debug information */ - int32_t *sourcemap; + DstSourceMapping *sourcemap; const uint8_t *source; const uint8_t *sourcepath;