1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-19 23:24:49 +00:00

Add boot script which is loaded on start up.

This commit is contained in:
bakpakin 2018-01-31 17:39:18 -05:00
parent 4f74d57359
commit 50bfa8de3f
10 changed files with 254 additions and 146 deletions

View File

@ -27,6 +27,18 @@ set (CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
include_directories(src/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Make tools for generating embeddable headers
add_executable(xxd src/tools/xxd.c)
# Generate header containing standard library
add_custom_command(
OUTPUT dststlbootstrap.h
COMMAND xxd ${CMAKE_CURRENT_SOURCE_DIR}/src/compiler/boot.dst dststlbootstrap.h dst_stl_bootstrap_gen
DEPENDS xxd src/compiler/boot.dst
COMMENT "Generating stl bootstrap C header for embedding"
)
set(ASSEMBLER_SOURCES
src/assembler/asm.c
@ -38,6 +50,7 @@ src/compiler/specials.c
src/compiler/cfuns.c
src/compiler/context.c
src/compiler/stl.c
dststlbootstrap.h
src/compiler/compile.h
)

78
src/compiler/boot.dst Normal file
View File

@ -0,0 +1,78 @@
(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)))
(def seq (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)})
(fn [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))
ret)
})
(defn doseq [s]
(def s (seq s))
(def more? (get s :more))
(def getnext (get s :next))
(while (more?)
(getnext)))
(defn map [f s]
(def s (seq s))
(def more (get s :more))
(def getnext (get s :next))
{
:more more
:next (fn [] (f (getnext)))
})
(defn reduce [f start s]
(def s (seq s))
(def more? (get s :more))
(def getnext (get s :next))
(var ret start)
(while (more?)
(varset! ret (f ret (getnext))))
ret)
(defmacro for [head & body]
(def head (ast-unwrap head))
(def sym (get head 0))
(def start (get head 1))
(def end (get head 2))
(def _inc (get head 3))
(def inc (if _inc _inc 1))
(tuple 'do
(tuple 'var sym start)
(tuple 'while (tuple '< sym end)
(tuple-prepend body 'do)
(tuple 'varset! sym (tuple '+ sym 1))
)))

View File

@ -45,21 +45,40 @@ static int replread(DstContext *c, enum DstParserStatus status) {
return 0;
}
static int cstringread(DstContext *c, enum DstParserStatus status) {
char *src = (char *)(c->user);
static int bytesread(DstContext *c, enum DstParserStatus status) {
const uint8_t *src = (const uint8_t *)(c->user);
(void) status;
int32_t n = CHUNKSIZE;
DstBuffer *b = &c->buffer;
if (!b->capacity) {
dst_buffer_ensure(b, CHUNKSIZE);
}
if (!*src) return 1;
while (*src && b->count < b->capacity) {
dst_buffer_push_u8(b, *src++);
}
if (!*src) {
b->count = 0;
if (!c->bufsize) {
dst_buffer_push_u8(b, '\n');
return 1;
}
c->user = src;
if (c->bufsize < n) n = c->bufsize;
dst_buffer_push_bytes(b, src, n);
c->bufsize -= n;
c->user = (void *)(src + n);
return 0;
}
/* Chunk readers */
static void filedeinit(DstContext *c) {
fclose((FILE *) (c->user));
}
/* Read chunk from file */
static int32_t fileread(DstContext *c, enum DstParserStatus status) {
size_t nread;
FILE *f = (FILE *) c->user;
(void) status;
c->buffer.count = 0;
dst_buffer_ensure(&c->buffer, CHUNKSIZE);
nread = fread(c->buffer.data, 1, CHUNKSIZE, f);
if (nread != CHUNKSIZE && ferror(f)) {
return -1;
}
c->buffer.count = (int32_t) nread;
return 0;
}
@ -90,23 +109,6 @@ static void simpleerror(DstContext *c, enum DstContextErrorType type, Dst err, s
dst_puts(dst_formatc("%s error: %s\n", errtype, dst_to_string(err)));
}
static void filedeinit(DstContext *c) {
fclose((FILE *) (c->user));
}
static int fileread(DstContext *c, enum DstParserStatus status) {
size_t nread;
FILE *f = (FILE *) c->user;
(void) status;
dst_buffer_ensure(&c->buffer, CHUNKSIZE);
nread = fread(c->buffer.data, 1, CHUNKSIZE, f);
if (nread != CHUNKSIZE && ferror(f)) {
return -1;
}
c->buffer.count = (int32_t) nread;
return 0;
}
void dst_context_init(DstContext *c, DstTable *env) {
dst_buffer_init(&c->buffer, CHUNKSIZE);
c->env = env;
@ -147,10 +149,11 @@ int dst_context_file(DstContext *c, DstTable *env, const char *path) {
return 0;
}
int dst_context_cstring(DstContext *c, DstTable *env, const char *source) {
int dst_context_bytes(DstContext *c, DstTable *env, const uint8_t *bytes, int32_t len) {
dst_context_init(c, env);
c->user = (void *) source;
c->read_chunk = cstringread;
c->user = (void *) bytes;
c->bufsize = len;
c->read_chunk = bytesread;
return 0;
}

View File

@ -27,13 +27,16 @@
#include <dst/dstparse.h>
#include <dst/dstcompile.h>
/* Generated header */
#include "dststlbootstrap.h"
static const DstReg cfuns[] = {
{"native", dst_core_native},
{"print", dst_core_print},
{"describe", dst_core_describe},
{"string", dst_core_string},
{"symbol", dst_core_symbol},
{"buffer-string", dst_core_buffer_to_string},
{"buffer", dst_core_buffer},
{"table", dst_core_table},
{"array", dst_core_array},
{"tuple", dst_core_tuple},
@ -53,10 +56,7 @@ static const DstReg cfuns[] = {
{NULL, NULL}
};
static const char *bootstrap =
"(def defmacro macro (fn [name & more] (tuple 'def name 'macro (tuple-prepend (tuple-prepend more name) 'fn))))\n"
"(defmacro defn [name & more] (tuple 'def name (tuple-prepend (tuple-prepend more name) 'fn)))\n"
"(defmacro when [cond & body] (tuple 'if cond (tuple-prepend body 'do)))\n";
#include <unistd.h>
DstTable *dst_stl_env() {
static uint32_t error_asm[] = {
@ -116,7 +116,7 @@ DstTable *dst_stl_env() {
/* Run bootstrap source */
{
DstContext ctxt;
dst_context_cstring(&ctxt, env, bootstrap);
dst_context_bytes(&ctxt, env, dst_stl_bootstrap_gen, sizeof(dst_stl_bootstrap_gen));
dst_context_run(&ctxt, 0);
}

View File

@ -55,8 +55,9 @@ int dst_core_describe(DstArgs args) {
for (j = 0; j < len; ++j) {
putc(vstr[j], stdout);
}
putc('\n', stdout);
}
putc('\n', stdout);
if (!i) putc('\n', stdout);
return 0;
}
@ -90,12 +91,16 @@ int dst_core_symbol(DstArgs args) {
return 0;
}
int dst_core_buffer_to_string(DstArgs args) {
DstBuffer *b;
if (args.n != 1) return dst_throw(args, "expected 1 argument");
if (!dst_checktype(args.v[0], DST_BUFFER)) return dst_throw(args, "expected buffer");
b = dst_unwrap_buffer(args.v[0]);
return dst_return(args, dst_wrap_string(dst_string(b->data, b->count)));
int dst_core_buffer(DstArgs args) {
int32_t i;
DstBuffer *b = dst_buffer(0);
for (i = 0; i < args.n; ++i) {
int32_t len;
const uint8_t *str = dst_to_string(args.v[i]);
len = dst_string_length(str);
dst_buffer_push_bytes(b, str, len);
}
return dst_return(args, dst_wrap_buffer(b));
}
int dst_core_tuple(DstArgs args) {
@ -139,17 +144,6 @@ int dst_core_fiber(DstArgs args) {
return dst_return(args, dst_wrap_fiber(fiber));
}
int dst_core_buffer(DstArgs args) {
DstBuffer *buffer = dst_buffer(10);
int32_t i;
for (i = 0; i < args.n; ++i) {
const uint8_t *bytes = dst_to_string(args.v[i]);
int32_t len = dst_string_length(bytes);
dst_buffer_push_bytes(buffer, bytes, len);
}
return dst_return(args, dst_wrap_buffer(buffer));
}
int dst_core_gensym(DstArgs args) {
if (args.n > 1) return dst_throw(args, "expected one argument");
if (args.n == 0) {

View File

@ -45,6 +45,7 @@ struct DstCompileResult {
};
DstCompileResult dst_compile(Dst source, DstTable *env, int flags);
int dst_compile_cfun(DstArgs args);
int dst_lib_compile(DstArgs args);
/* Context - for executing dst in the interpretted form. */
typedef struct DstContext DstContext;
@ -52,13 +53,17 @@ typedef struct DstContext DstContext;
/* Get the default environment for dst */
DstTable *dst_stl_env();
/* Different levels of reporting and configuration */
void dst_context_init(DstContext *c, DstTable *env);
void dst_context_deinit(DstContext *c);
int dst_context_repl(DstContext *c, DstTable *env);
int dst_context_file(DstContext *c, DstTable *env, const char *path);
int dst_context_cstring(DstContext *c, DstTable *env, const char *source);
int dst_context_repl(DstContext *c, DstTable *env);
int dst_context_bytes(DstContext *c, DstTable *env, const uint8_t *bytes, int32_t len);
/* Evaluate a form in the context */
int dst_context_run(DstContext *c, int flags);
void dst_context_deinit(DstContext *c);
/* Parse structs */
enum DstContextErrorType {
DST_CONTEXT_ERROR_PARSE,
@ -72,6 +77,7 @@ struct DstContext {
DstTable *env;
DstBuffer buffer;
void *user;
int32_t bufsize;
int32_t index;
int (*read_chunk)(DstContext *self, enum DstParserStatus status);
@ -80,8 +86,6 @@ struct DstContext {
void (*deinit)(DstContext *self);
};
int dst_lib_compile(DstArgs args);
#ifdef __cplusplus
}
#endif

View File

@ -20,8 +20,8 @@
* IN THE SOFTWARE.
*/
#ifndef DST_MATH_H_defined
#define DST_MATH_H_defined
#ifndef DST_CORELIB_H_defined
#define DST_CORELIB_H_defined
#ifdef __cplusplus
extern "C" {
@ -29,12 +29,6 @@ extern "C" {
#include "dsttypes.h"
/* Basic C Functions. These are good
* candidates for optimizations like bytecode
* inlining and costant folding. They are exposed publicly
* so that compiles can inject them into funcdefs. Later, a
* different serialization mechanism might be used for cfunctions. */
/* Native */
int dst_core_native(DstArgs args);
@ -80,7 +74,7 @@ int dst_core_print(DstArgs args);
int dst_core_describe(DstArgs args);
int dst_core_string(DstArgs args);
int dst_core_symbol(DstArgs args);
int dst_core_buffer_to_string(DstArgs args);
int dst_core_buffer(DstArgs args);
int dst_core_tuple(DstArgs args);
int dst_core_array(DstArgs args);
int dst_core_table(DstArgs args);
@ -113,4 +107,4 @@ Dst dst_op_subtract(Dst lhs, Dst rhs);
}
#endif
#endif /* DST_MATH_H_defined */
#endif /* DST_CORELIB_H_defined */

View File

@ -62,6 +62,7 @@ int dst_parser_consume(DstParser *parser, uint8_t c);
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);
int dst_lib_parse(DstArgs args);

97
src/tools/xxd.c Normal file
View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2018 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.
*/
/* Simple clone of the xxd tool used at build time. Used to
* create headers out of source files. Only used for core libraries
* like the bootstrapping code and the stl. */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#define BUFSIZE 1024
#define PERLINE 10
int main(int argc, const char **argv) {
static const char hex[] = "0123456789ABCDEF";
char buf[BUFSIZE];
size_t bytesRead = 0;
int lineIndex = 0;
int line = 0;
if (argc != 4) {
fprintf(stderr, "Usage: %s infile outfile symbol\n", argv[0]);
return 1;
}
/* Open the files */
FILE *in = fopen(argv[1], "rb");
FILE *out = fopen(argv[2], "wb");
/* Check if files open successfully */
if (in == NULL) {
fprintf(stderr, "Could not open input file %s\n", argv[1]);
return 1;
} else if (out == NULL) {
fprintf(stderr, "Could not open output file %s\n", argv[2]);
return 1;
}
/* Write the header */
fprintf(out, "/* Auto generated - DO NOT EDIT */\n\n");
fprintf(out, "static const unsigned char %s[] = {", argv[3]);
/* Read in chunks from buffer */
while ((bytesRead = fread(buf, 1, sizeof(buf), in)) > 0) {
size_t i;
for (i = 0; i < bytesRead; ++i) {
int byte = ((uint8_t *)buf) [i];
/* Write the byte */
if (lineIndex++ == 0) {
if (line++)
fputc(',', out);
fputs("\n\t", out);
} else {
fputs(", ", out);
}
fputs("0x", out);
fputc(hex[byte >> 4], out);
fputc(hex[byte & 0xF], out);
/* Make line index wrap */
if (lineIndex >= PERLINE)
lineIndex = 0;
}
}
/* Write the tail */
fputs("\n};\n\n", out);
/* Close the file handles */
fclose(in);
fclose(out);
return 0;
}

View File

@ -1,76 +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.
# 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))
})