mirror of
https://github.com/janet-lang/janet
synced 2024-09-29 23:40:40 +00:00
Change convention for naming modules and functions.
This commit is contained in:
parent
8fd8b1126b
commit
f47323c915
@ -65,7 +65,8 @@ $
|
|||||||
## Docmentation
|
## Docmentation
|
||||||
|
|
||||||
API documentation and design documents will be added to the `doc` folder as they are written.
|
API documentation and design documents will be added to the `doc` folder as they are written.
|
||||||
As of March 2018, specifications are sparse because dst is evolving.
|
As of March 2018, specifications are sparse because dst is evolving. Check the doc folder for
|
||||||
|
an introduction of Dst as well as an overview of the bytecode format.
|
||||||
|
|
||||||
## Compiling and Running
|
## Compiling and Running
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Example of dst bytecode assembly
|
# Example of dst bytecode assembly
|
||||||
|
|
||||||
# Fibonacci sequence, implemented with naive recursion.
|
# Fibonacci sequence, implemented with naive recursion.
|
||||||
(def fibasm (asm '{
|
(def fibasm (asm/asm '{
|
||||||
arity 1
|
arity 1
|
||||||
bytecode [
|
bytecode [
|
||||||
(ldi 1 0x2) # $1 = 2
|
(ldi 1 0x2) # $1 = 2
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
(defn iter2array [itr]
|
(defn iter2array [itr]
|
||||||
(def {:more more :next next} (iter itr))
|
(def {:more more :next next} (iter itr))
|
||||||
(def a @[])
|
(def a @[])
|
||||||
(while (more) (array-push a (next)))
|
(while (more) (array.push a (next)))
|
||||||
a)
|
a)
|
||||||
|
|
||||||
(defn map [f itr]
|
(defn map [f itr]
|
||||||
|
@ -18,7 +18,7 @@ body once, and then memoizes the result."
|
|||||||
$state
|
$state
|
||||||
(tuple 'do
|
(tuple 'do
|
||||||
(tuple ':= $loaded true)
|
(tuple ':= $loaded true)
|
||||||
(tuple ':= $state (tuple-prepend forms 'do)))))))
|
(tuple ':= $state (tuple.prepend forms 'do)))))))
|
||||||
|
|
||||||
# Use tuples instead of structs to save memory
|
# Use tuples instead of structs to save memory
|
||||||
(def HEAD :private 0)
|
(def HEAD :private 0)
|
||||||
@ -129,14 +129,3 @@ body once, and then memoizes the result."
|
|||||||
(when-let [n (node)]
|
(when-let [n (node)]
|
||||||
(:= node (get n 1))
|
(:= node (get n 1))
|
||||||
(get n 0)))})
|
(get n 0)))})
|
||||||
|
|
||||||
# Now we can use the non-functional filter from boot.dst
|
|
||||||
# to write a filter version that returns a lazy sequence
|
|
||||||
# Be careful when creating lazy sequences from mutable
|
|
||||||
# data structures as their values are references to this
|
|
||||||
# data structures. Same is true for iterators
|
|
||||||
|
|
||||||
(defn filter2 [pred coll] (iter2lazy (filter pred coll)))
|
|
||||||
|
|
||||||
# be careful with the filter function. First element in (filter pos? arr) is nil
|
|
||||||
# last element is false
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
# of the triangle to the leaves of the triangle.
|
# of the triangle to the leaves of the triangle.
|
||||||
|
|
||||||
(defn myfold [xs ys]
|
(defn myfold [xs ys]
|
||||||
(def xs1 (tuple-prepend xs 0))
|
(let [xs1 (tuple.prepend xs 0)
|
||||||
(def xs2 (tuple-append xs 0))
|
xs2 (tuple.append xs 0)
|
||||||
(def m1 (map + xs1 ys))
|
m1 (map + xs1 ys)
|
||||||
(def m2 (map + xs2 ys))
|
m2 (map + xs2 ys)]
|
||||||
(map max m1 m2))
|
(map max m1 m2)))
|
||||||
|
|
||||||
(defn maxpath [t]
|
(defn maxpath [t]
|
||||||
(extreme > (reduce myfold () t)))
|
(extreme > (reduce myfold () t)))
|
||||||
|
@ -10,5 +10,5 @@
|
|||||||
(for [j 0 len]
|
(for [j 0 len]
|
||||||
(def trial (get list j))
|
(def trial (get list j))
|
||||||
(if (zero? (% i trial)) (:= isprime? false)))
|
(if (zero? (% i trial)) (:= isprime? false)))
|
||||||
(if isprime? (array-push list i)))
|
(if isprime? (array.push list i)))
|
||||||
list)
|
list)
|
||||||
|
@ -38,7 +38,7 @@ static int gcsqlite(void *p, size_t s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstAbstractType sql_conn_type = {
|
static const DstAbstractType sql_conn_type = {
|
||||||
":sqlite3.conn",
|
":sqlite3.connection",
|
||||||
gcsqlite,
|
gcsqlite,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
@ -77,15 +77,15 @@ static int sql_close(DstArgs args) {
|
|||||||
static int sql_execute_callback(void *rowsp, int n, char **vals, char **colnames) {
|
static int sql_execute_callback(void *rowsp, int n, char **vals, char **colnames) {
|
||||||
int i;
|
int i;
|
||||||
DstArray *rows = (DstArray *)rowsp;
|
DstArray *rows = (DstArray *)rowsp;
|
||||||
DstTable *row = dst_table(n);
|
DstKV *row = dst_struct_begin(n);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
dst_table_put(row, dst_cstringv(colnames[i]), dst_cstringv(vals[i]));
|
dst_struct_put(row, dst_cstringv(colnames[i]), dst_cstringv(vals[i]));
|
||||||
}
|
}
|
||||||
dst_array_push(rows, dst_wrap_table(row));
|
dst_array_push(rows, dst_wrap_struct(dst_struct_end(row)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sql_execute(DstArgs args) {
|
static int sql_sql(DstArgs args) {
|
||||||
int status;
|
int status;
|
||||||
char *errmsg = "connection closed";
|
char *errmsg = "connection closed";
|
||||||
const uint8_t *str;
|
const uint8_t *str;
|
||||||
@ -121,7 +121,7 @@ static int sql_rowid(DstArgs args) {}
|
|||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"open", sql_open},
|
{"open", sql_open},
|
||||||
{"close", sql_close},
|
{"close", sql_close},
|
||||||
{"execute", sql_execute},
|
{"sql", sql_sql},
|
||||||
/*{"tables", sql_tables},*/
|
/*{"tables", sql_tables},*/
|
||||||
/*{"changes", sql_changes},*/
|
/*{"changes", sql_changes},*/
|
||||||
/*{"timeout", sql_timeout},*/
|
/*{"timeout", sql_timeout},*/
|
||||||
|
@ -908,8 +908,8 @@ int dst_disasm_cfun(DstArgs args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"asm", dst_asm_cfun},
|
{"asm/asm", dst_asm_cfun},
|
||||||
{"disasm", dst_disasm_cfun},
|
{"asm/disasm", dst_disasm_cfun},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,19 +12,19 @@
|
|||||||
_env)
|
_env)
|
||||||
|
|
||||||
(def defn :macro
|
(def defn :macro
|
||||||
"Define a function"
|
"Define a function. Equivalent to (def name (fn name [args] ...))."
|
||||||
(fn [name & more]
|
(fn [name & more]
|
||||||
(def len (length more))
|
(def len (length more))
|
||||||
(def fstart (fn recur [i]
|
(def fstart (fn recur [i]
|
||||||
(def ith (ast-unwrap1 (get more i)))
|
(def ith (ast.unwrap1 (get more i)))
|
||||||
(def t (type ith))
|
(def t (type ith))
|
||||||
(def tuple? (= t :tuple))
|
(def tuple? (= t :tuple))
|
||||||
(def array? (= t :array))
|
(def array? (= t :array))
|
||||||
(if (if tuple? tuple? array?) i
|
(if (if tuple? tuple? array?) i
|
||||||
(if (< i len) (recur (+ i 1))))))
|
(if (< i len) (recur (+ i 1))))))
|
||||||
(def start (fstart 0))
|
(def start (fstart 0))
|
||||||
(def fnbody (tuple-prepend (tuple-prepend (tuple-slice more start) name) 'fn))
|
(def fnbody (tuple.prepend (tuple.prepend (tuple.slice more start) name) 'fn))
|
||||||
(def formargs (array-concat @['def name] (array-slice more 0 start) @[fnbody]))
|
(def formargs (array.concat @['def name] (array.slice more 0 start) @[fnbody]))
|
||||||
(apply1 tuple formargs)))
|
(apply1 tuple formargs)))
|
||||||
|
|
||||||
(def defmacro :macro
|
(def defmacro :macro
|
||||||
@ -32,39 +32,39 @@
|
|||||||
(do
|
(do
|
||||||
(def defn* (get (get _env 'defn) :value))
|
(def defn* (get (get _env 'defn) :value))
|
||||||
(fn [name & more]
|
(fn [name & more]
|
||||||
(apply1 defn* (array-concat
|
(apply1 defn* (array.concat
|
||||||
@[name :macro] more)))))
|
@[name :macro] more)))))
|
||||||
|
|
||||||
(defmacro defmacro-
|
(defmacro defmacro-
|
||||||
"Define a private macro that will not be exported."
|
"Define a private macro that will not be exported."
|
||||||
[name & more]
|
[name & more]
|
||||||
(apply1 tuple (array-concat
|
(apply1 tuple (array.concat
|
||||||
@['defmacro name :private] more)))
|
@['defmacro name :private] more)))
|
||||||
|
|
||||||
(defmacro defdo
|
(defmacro defdo
|
||||||
"Define a value inside of a do form."
|
"Define a value inside of a do form."
|
||||||
[name & more]
|
[name & more]
|
||||||
(apply1 tuple (array-concat
|
(apply1 tuple (array.concat
|
||||||
@['def name]
|
@['def name]
|
||||||
(apply1 tuple (array-concat @['do] more)))))
|
(apply1 tuple (array.concat @['do] more)))))
|
||||||
|
|
||||||
(defmacro defdo-
|
(defmacro defdo-
|
||||||
"Define a private value inside of a do form."
|
"Define a private value inside of a do form."
|
||||||
[name & more]
|
[name & more]
|
||||||
(apply1 tuple (array-concat
|
(apply1 tuple (array.concat
|
||||||
@['def name :private]
|
@['def name :private]
|
||||||
(apply1 tuple (array-concat @['do] more)))))
|
(apply1 tuple (array.concat @['do] more)))))
|
||||||
|
|
||||||
(defmacro defn-
|
(defmacro defn-
|
||||||
"Define a private function that will not be exported."
|
"Define a private function that will not be exported."
|
||||||
[name & more]
|
[name & more]
|
||||||
(apply1 tuple (array-concat
|
(apply1 tuple (array.concat
|
||||||
@['defn name :private] more)))
|
@['defn name :private] more)))
|
||||||
|
|
||||||
(defmacro def-
|
(defmacro def-
|
||||||
"Define a private value that will not be exported."
|
"Define a private value that will not be exported."
|
||||||
[name & more]
|
[name & more]
|
||||||
(apply1 tuple (array-concat
|
(apply1 tuple (array.concat
|
||||||
@['def name :private] more)))
|
@['def name :private] more)))
|
||||||
|
|
||||||
# Basic predicates
|
# Basic predicates
|
||||||
@ -132,12 +132,12 @@ Expands to (def sym (if (= nil sym) val sym))"
|
|||||||
(defmacro when
|
(defmacro when
|
||||||
"Evaluates the body when the condition is true. Otherwise returns nil."
|
"Evaluates the body when the condition is true. Otherwise returns nil."
|
||||||
[condition & body]
|
[condition & body]
|
||||||
(tuple 'if condition (tuple-prepend body 'do)))
|
(tuple 'if condition (tuple.prepend body 'do)))
|
||||||
|
|
||||||
(defmacro when-not
|
(defmacro when-not
|
||||||
"Shorthand for (when (not ... "
|
"Shorthand for (when (not ... "
|
||||||
[condition & body]
|
[condition & body]
|
||||||
(tuple 'if condition nil (tuple-prepend body 'do)))
|
(tuple 'if condition nil (tuple.prepend body 'do)))
|
||||||
|
|
||||||
(defmacro cond
|
(defmacro cond
|
||||||
"Evaluates conditions sequentially until the first true condition
|
"Evaluates conditions sequentially until the first true condition
|
||||||
@ -174,14 +174,14 @@ tuple and will be spliced into the function call. For example, (apply + 1 2 @[3
|
|||||||
evaluates to 10."
|
evaluates to 10."
|
||||||
[f & args]
|
[f & args]
|
||||||
(def last (- (length args) 1))
|
(def last (- (length args) 1))
|
||||||
(apply1 f (array-concat (array-slice args 0 -2) (get args last))))
|
(apply1 f (array.concat (array.slice args 0 -2) (get args last))))
|
||||||
|
|
||||||
(defmacro switch
|
(defmacro switch
|
||||||
"Select the body that equals the dispatch value. When pairs
|
"Select the body that equals the dispatch value. When pairs
|
||||||
has an odd number of arguments, the last is the default expression.
|
has an odd number of arguments, the last is the default expression.
|
||||||
If no match is found, returns nil"
|
If no match is found, returns nil"
|
||||||
[dispatch & pairs]
|
[dispatch & pairs]
|
||||||
(def atm (atomic? (ast-unwrap1 dispatch)))
|
(def atm (atomic? (ast.unwrap1 dispatch)))
|
||||||
(def sym (if atm dispatch (gensym)))
|
(def sym (if atm dispatch (gensym)))
|
||||||
(defn aux [i]
|
(defn aux [i]
|
||||||
(def restlen (- (length pairs) i))
|
(def restlen (- (length pairs) i))
|
||||||
@ -201,30 +201,30 @@ If no match is found, returns nil"
|
|||||||
assigned as if with def, and the body of the let form returns the last
|
assigned as if with def, and the body of the let form returns the last
|
||||||
value."
|
value."
|
||||||
[bindings & body]
|
[bindings & body]
|
||||||
(def head (ast-unwrap1 bindings))
|
(def head (ast.unwrap1 bindings))
|
||||||
(if (odd? (length head)) (error "expected even number of bindings to let"))
|
(if (odd? (length head)) (error "expected even number of bindings to let"))
|
||||||
(def len (length head))
|
(def len (length head))
|
||||||
(var i 0)
|
(var i 0)
|
||||||
(var accum @['do])
|
(var accum @['do])
|
||||||
(while (< i len)
|
(while (< i len)
|
||||||
(array-push accum (tuple 'def
|
(array.push accum (tuple 'def
|
||||||
(get head i)
|
(get head i)
|
||||||
(get head (+ 1 i))))
|
(get head (+ 1 i))))
|
||||||
(+= i 2))
|
(+= i 2))
|
||||||
(array-concat accum body)
|
(array.concat accum body)
|
||||||
(apply1 tuple accum))
|
(apply1 tuple accum))
|
||||||
|
|
||||||
(defmacro for
|
(defmacro for
|
||||||
"An imperative for loop over an integer range. Use with caution and discretion."
|
"An imperative for loop over an integer range. Use with caution and discretion."
|
||||||
[head & body]
|
[head & body]
|
||||||
(def [sym start end _inc] (ast-unwrap1 head))
|
(def [sym start end _inc] (ast.unwrap1 head))
|
||||||
(def inc (if _inc _inc 1))
|
(def inc (if _inc _inc 1))
|
||||||
(def endsym (gensym))
|
(def endsym (gensym))
|
||||||
(tuple 'do
|
(tuple 'do
|
||||||
(tuple 'var sym start)
|
(tuple 'var sym start)
|
||||||
(tuple 'def endsym end)
|
(tuple 'def endsym end)
|
||||||
(tuple 'while (tuple < sym endsym)
|
(tuple 'while (tuple < sym endsym)
|
||||||
(tuple-prepend body 'do)
|
(tuple.prepend body 'do)
|
||||||
(tuple ':= sym (tuple + sym inc)))))
|
(tuple ':= sym (tuple + sym inc)))))
|
||||||
|
|
||||||
(defmacro and
|
(defmacro and
|
||||||
@ -247,7 +247,7 @@ evaluates to true."
|
|||||||
(if
|
(if
|
||||||
(>= (inc i) len) fi
|
(>= (inc i) len) fi
|
||||||
(do
|
(do
|
||||||
(if (atomic? (ast-unwrap1 fi))
|
(if (atomic? (ast.unwrap1 fi))
|
||||||
(tuple 'if fi fi (aux (inc i)))
|
(tuple 'if fi fi (aux (inc i)))
|
||||||
(do
|
(do
|
||||||
(def $fi (gensym))
|
(def $fi (gensym))
|
||||||
@ -264,7 +264,7 @@ evaluates to true."
|
|||||||
all the forms with let and evaluates the first expression else
|
all the forms with let and evaluates the first expression else
|
||||||
evaluates the second"
|
evaluates the second"
|
||||||
[bindings tru fal]
|
[bindings tru fal]
|
||||||
(def bindings (ast-unwrap1 bindings))
|
(def bindings (ast.unwrap1 bindings))
|
||||||
(def len (length bindings))
|
(def len (length bindings))
|
||||||
(if (zero? len) (error "expected at least 1 binding"))
|
(if (zero? len) (error "expected at least 1 binding"))
|
||||||
(if (odd? len) (error "expected an even number of bindings"))
|
(if (odd? len) (error "expected an even number of bindings"))
|
||||||
@ -274,7 +274,7 @@ evaluates to true."
|
|||||||
(if (>= i len)
|
(if (>= i len)
|
||||||
tru
|
tru
|
||||||
(do
|
(do
|
||||||
(def atm (atomic? (ast-unwrap1 bl)))
|
(def atm (atomic? (ast.unwrap1 bl)))
|
||||||
(def sym (if atm bl (gensym)))
|
(def sym (if atm bl (gensym)))
|
||||||
(if atm
|
(if atm
|
||||||
# Simple binding
|
# Simple binding
|
||||||
@ -295,7 +295,7 @@ evaluates to true."
|
|||||||
"Takes the first one or two forms in vector and if true binds
|
"Takes the first one or two forms in vector and if true binds
|
||||||
all the forms with let and evaluates the body"
|
all the forms with let and evaluates the body"
|
||||||
[bindings & body]
|
[bindings & body]
|
||||||
(tuple 'if-let bindings (tuple-prepend body 'do)))
|
(tuple 'if-let bindings (tuple.prepend body 'do)))
|
||||||
|
|
||||||
(defn comp
|
(defn comp
|
||||||
"Takes multiple functions and returns a function that is the composition
|
"Takes multiple functions and returns a function that is the composition
|
||||||
@ -309,7 +309,7 @@ evaluates to true."
|
|||||||
4 (let [[f g h i] functions] (fn [x] (f (g (h (i x))))))
|
4 (let [[f g h i] functions] (fn [x] (f (g (h (i x))))))
|
||||||
(let [[f g h i j] functions]
|
(let [[f g h i j] functions]
|
||||||
(apply comp (fn [x] (f (g (h (i (j x))))))
|
(apply comp (fn [x] (f (g (h (i (j x))))))
|
||||||
(tuple-slice functions 5 -1)))))
|
(tuple.slice functions 5 -1)))))
|
||||||
|
|
||||||
(defn identity
|
(defn identity
|
||||||
"A function that returns its first argument."
|
"A function that returns its first argument."
|
||||||
@ -404,14 +404,14 @@ the same type as the input sequence."
|
|||||||
(if (< l limit) (:= limit l)))
|
(if (< l limit) (:= limit l)))
|
||||||
(def [i1 i2 i3 i4] inds)
|
(def [i1 i2 i3 i4] inds)
|
||||||
(switch ninds
|
(switch ninds
|
||||||
1 (for [i 0 limit] (array-push res (f (get i1 i))))
|
1 (for [i 0 limit] (array.push res (f (get i1 i))))
|
||||||
2 (for [i 0 limit] (array-push res (f (get i1 i) (get i2 i))))
|
2 (for [i 0 limit] (array.push res (f (get i1 i) (get i2 i))))
|
||||||
3 (for [i 0 limit] (array-push res (f (get i1 i) (get i2 i) (get i3 i))))
|
3 (for [i 0 limit] (array.push res (f (get i1 i) (get i2 i) (get i3 i))))
|
||||||
4 (for [i 0 limit] (array-push res (f (get i1 i) (get i2 i) (get i3 i) (get i4 i))))
|
4 (for [i 0 limit] (array.push res (f (get i1 i) (get i2 i) (get i3 i) (get i4 i))))
|
||||||
(for [i 0 limit]
|
(for [i 0 limit]
|
||||||
(def args @[])
|
(def args @[])
|
||||||
(for [j 0 ninds] (array-push args (get (get inds j) i)))
|
(for [j 0 ninds] (array.push args (get (get inds j) i)))
|
||||||
(array-push res (apply1 f args))))
|
(array.push res (apply1 f args))))
|
||||||
res)
|
res)
|
||||||
|
|
||||||
(defn each
|
(defn each
|
||||||
@ -432,7 +432,7 @@ return a new indexed type."
|
|||||||
4 (for [i 0 limit] (f (get i1 i) (get i2 i) (get i3 i) (get i4 i)))
|
4 (for [i 0 limit] (f (get i1 i) (get i2 i) (get i3 i) (get i4 i)))
|
||||||
(for [i 0 limit]
|
(for [i 0 limit]
|
||||||
(def args @[])
|
(def args @[])
|
||||||
(for [j 0 ninds] (array-push args (get (get inds j) i)))
|
(for [j 0 ninds] (array.push args (get (get inds j) i)))
|
||||||
(apply1 f args))))
|
(apply1 f args))))
|
||||||
|
|
||||||
(defn mapcat
|
(defn mapcat
|
||||||
@ -442,7 +442,7 @@ type as the input sequence."
|
|||||||
[f ind t]
|
[f ind t]
|
||||||
(def res @[])
|
(def res @[])
|
||||||
(for [i 0 (length ind)]
|
(for [i 0 (length ind)]
|
||||||
(array-concat res (f (get ind i))))
|
(array.concat res (f (get ind i))))
|
||||||
(if (= :tuple (type (or t ind)))
|
(if (= :tuple (type (or t ind)))
|
||||||
(apply1 tuple res)
|
(apply1 tuple res)
|
||||||
res))
|
res))
|
||||||
@ -455,7 +455,7 @@ which (pred element) is truthy. Returns the same type as the input sequence."
|
|||||||
(for [i 0 (length ind)]
|
(for [i 0 (length ind)]
|
||||||
(def item (get ind i))
|
(def item (get ind i))
|
||||||
(if (pred item)
|
(if (pred item)
|
||||||
(array-push res item)))
|
(array.push res item)))
|
||||||
(if (= :tuple (type (or t ind)))
|
(if (= :tuple (type (or t ind)))
|
||||||
(apply1 tuple res)
|
(apply1 tuple res)
|
||||||
res))
|
res))
|
||||||
@ -485,8 +485,8 @@ the same type as the input."
|
|||||||
[pred ind t]
|
[pred ind t]
|
||||||
(def i (find-index pred ind))
|
(def i (find-index pred ind))
|
||||||
(if (= :tuple (type (or t ind)))
|
(if (= :tuple (type (or t ind)))
|
||||||
(tuple-slice ind 0 i)
|
(tuple.slice ind 0 i)
|
||||||
(array-slice ind 0 i)))
|
(array.slice ind 0 i)))
|
||||||
|
|
||||||
(defn take-while
|
(defn take-while
|
||||||
"Same as (take-until (complement pred) ind t)."
|
"Same as (take-until (complement pred) ind t)."
|
||||||
@ -499,8 +499,8 @@ the predicate, and abort on first failure."
|
|||||||
[pred ind t]
|
[pred ind t]
|
||||||
(def i (find-index pred ind))
|
(def i (find-index pred ind))
|
||||||
(if (= :tuple (type (or t ind)))
|
(if (= :tuple (type (or t ind)))
|
||||||
(tuple-slice ind i -1)
|
(tuple.slice ind i -1)
|
||||||
(array-slice ind i -1)))
|
(array.slice ind i -1)))
|
||||||
|
|
||||||
(defn drop-while
|
(defn drop-while
|
||||||
"Same as (drop-until (complement pred) ind t)."
|
"Same as (drop-until (complement pred) ind t)."
|
||||||
@ -513,7 +513,7 @@ the predicate, and abort on first failure."
|
|||||||
(fn [& args]
|
(fn [& args]
|
||||||
(def ret @[])
|
(def ret @[])
|
||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
(array-push ret (apply1 (get funs i) args)))
|
(array.push ret (apply1 (get funs i) args)))
|
||||||
(apply1 tuple ret)))
|
(apply1 tuple ret)))
|
||||||
|
|
||||||
(defmacro juxt
|
(defmacro juxt
|
||||||
@ -521,7 +521,7 @@ the predicate, and abort on first failure."
|
|||||||
(def parts @['tuple])
|
(def parts @['tuple])
|
||||||
(def $args (gensym))
|
(def $args (gensym))
|
||||||
(for [i 0 (length funs)]
|
(for [i 0 (length funs)]
|
||||||
(array-push parts (tuple apply1 (get funs i) $args)))
|
(array.push parts (tuple apply1 (get funs i) $args)))
|
||||||
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
||||||
|
|
||||||
(defmacro ->
|
(defmacro ->
|
||||||
@ -530,11 +530,11 @@ in form, and inserts the modified firsts form into the second form
|
|||||||
in the same manner, and so on. Useful for expressing pipelines of data."
|
in the same manner, and so on. Useful for expressing pipelines of data."
|
||||||
[x & forms]
|
[x & forms]
|
||||||
(defn fop [last nextform]
|
(defn fop [last nextform]
|
||||||
(def n (ast-unwrap1 nextform))
|
(def n (ast.unwrap1 nextform))
|
||||||
(def [h t] (if (= :tuple (type n))
|
(def [h t] (if (= :tuple (type n))
|
||||||
[tuple (get n 0) (array-slice n 1)]
|
[tuple (get n 0) (array.slice n 1)]
|
||||||
[tuple n @[]]))
|
[tuple n @[]]))
|
||||||
(def parts (array-concat @[h last] t))
|
(def parts (array.concat @[h last] t))
|
||||||
(apply1 tuple parts))
|
(apply1 tuple parts))
|
||||||
(reduce fop x forms))
|
(reduce fop x forms))
|
||||||
|
|
||||||
@ -544,11 +544,11 @@ in form, and inserts the modified firsts form into the second form
|
|||||||
in the same manner, and so on. Useful for expressing pipelines of data."
|
in the same manner, and so on. Useful for expressing pipelines of data."
|
||||||
[x & forms]
|
[x & forms]
|
||||||
(defn fop [last nextform]
|
(defn fop [last nextform]
|
||||||
(def n (ast-unwrap1 nextform))
|
(def n (ast.unwrap1 nextform))
|
||||||
(def [h t] (if (= :tuple (type n))
|
(def [h t] (if (= :tuple (type n))
|
||||||
[tuple (get n 0) (array-slice n 1)]
|
[tuple (get n 0) (array.slice n 1)]
|
||||||
[tuple n @[]]))
|
[tuple n @[]]))
|
||||||
(def parts (array-concat @[h] t @[last]))
|
(def parts (array.concat @[h] t @[last]))
|
||||||
(apply1 tuple parts))
|
(apply1 tuple parts))
|
||||||
(reduce fop x forms))
|
(reduce fop x forms))
|
||||||
|
|
||||||
@ -556,7 +556,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
"Partial function application."
|
"Partial function application."
|
||||||
[f & more]
|
[f & more]
|
||||||
(if (zero? (length more)) f
|
(if (zero? (length more)) f
|
||||||
(fn [& r] (apply1 f (array-concat @[] more r)))))
|
(fn [& r] (apply1 f (array.concat @[] more r)))))
|
||||||
|
|
||||||
(defn every? [pred seq]
|
(defn every? [pred seq]
|
||||||
(var res true)
|
(var res true)
|
||||||
@ -569,27 +569,27 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(do (:= res false) (:= i len))))
|
(do (:= res false) (:= i len))))
|
||||||
res)
|
res)
|
||||||
|
|
||||||
(defn reverse-array
|
(defn array.reverse
|
||||||
"Reverses the order of the elements in a given array or tuple and returns a new array."
|
"Reverses the order of the elements in a given array or tuple and returns a new array."
|
||||||
[t]
|
[t]
|
||||||
(var n (dec (length t)))
|
(var n (dec (length t)))
|
||||||
(var reversed @[])
|
(var reversed @[])
|
||||||
(while (>= n 0)
|
(while (>= n 0)
|
||||||
(array-push reversed (get t n))
|
(array.push reversed (get t n))
|
||||||
(-- n))
|
(-- n))
|
||||||
reversed)
|
reversed)
|
||||||
|
|
||||||
(defn reverse-tuple
|
(defn tuple.reverse
|
||||||
"Reverses the order of the elements given an array or tuple and returns a tuple"
|
"Reverses the order of the elements given an array or tuple and returns a tuple"
|
||||||
[t]
|
[t]
|
||||||
(apply1 tuple (reverse-array t)))
|
(apply1 tuple (array.reverse t)))
|
||||||
|
|
||||||
(defn reverse
|
(defn reverse
|
||||||
"Reverses order of elements in a given array or tuple"
|
"Reverses order of elements in a given array or tuple"
|
||||||
[t]
|
[t]
|
||||||
(switch (type t)
|
((switch (type t)
|
||||||
:tuple (reverse-tuple t)
|
:tuple tuple.reverse
|
||||||
:array (reverse-array t)))
|
:array array.reverse) t))
|
||||||
|
|
||||||
(defn zipcoll
|
(defn zipcoll
|
||||||
"Creates an table or tuple from two arrays/tuples. If a third argument of
|
"Creates an table or tuple from two arrays/tuples. If a third argument of
|
||||||
@ -602,7 +602,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
(put res (get keys i) (get vals i)))
|
(put res (get keys i) (get vals i)))
|
||||||
(if (= :struct t)
|
(if (= :struct t)
|
||||||
(table-to-struct res)
|
(table.to-struct res)
|
||||||
res))
|
res))
|
||||||
|
|
||||||
(defn update
|
(defn update
|
||||||
@ -625,7 +625,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(while (not= nil key)
|
(while (not= nil key)
|
||||||
(put container key (get c key))
|
(put container key (get c key))
|
||||||
(:= key (next c key))))
|
(:= key (next c key))))
|
||||||
(if (table? (get colls 0)) container (table-to-struct container)))
|
(if (table? (get colls 0)) container (table.to-struct container)))
|
||||||
|
|
||||||
(defn keys
|
(defn keys
|
||||||
"Get the keys of an associative data structure."
|
"Get the keys of an associative data structure."
|
||||||
@ -633,7 +633,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(def arr @[])
|
(def arr @[])
|
||||||
(var k (next x nil))
|
(var k (next x nil))
|
||||||
(while (not= nil k)
|
(while (not= nil k)
|
||||||
(array-push arr k)
|
(array.push arr k)
|
||||||
(:= k (next x k)))
|
(:= k (next x k)))
|
||||||
arr)
|
arr)
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(def arr @[])
|
(def arr @[])
|
||||||
(var k (next x nil))
|
(var k (next x nil))
|
||||||
(while (not= nil k)
|
(while (not= nil k)
|
||||||
(array-push arr (get x k))
|
(array.push arr (get x k))
|
||||||
(:= k (next x k)))
|
(:= k (next x k)))
|
||||||
arr)
|
arr)
|
||||||
|
|
||||||
@ -653,7 +653,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(def arr @[])
|
(def arr @[])
|
||||||
(var k (next x nil))
|
(var k (next x nil))
|
||||||
(while (not= nil k)
|
(while (not= nil k)
|
||||||
(array-push arr (tuple k (get x k)))
|
(array.push arr (tuple k (get x k)))
|
||||||
(:= k (next x k)))
|
(:= k (next x k)))
|
||||||
arr)
|
arr)
|
||||||
|
|
||||||
@ -681,49 +681,49 @@ to call on any table. Does not print table prototype information."
|
|||||||
(def id (get seen y))
|
(def id (get seen y))
|
||||||
(if (and checkcycle id)
|
(if (and checkcycle id)
|
||||||
(do
|
(do
|
||||||
(buffer-push-string buf "<cycle ")
|
(buffer.push-string buf "<cycle ")
|
||||||
(buffer-push-string buf (string id))
|
(buffer.push-string buf (string id))
|
||||||
(buffer-push-string buf ">"))
|
(buffer.push-string buf ">"))
|
||||||
(do
|
(do
|
||||||
(put seen y (++ nextid))
|
(put seen y (++ nextid))
|
||||||
(buffer-push-string buf start)
|
(buffer.push-string buf start)
|
||||||
(dispatch y)
|
(dispatch y)
|
||||||
(buffer-push-string buf end))))
|
(buffer.push-string buf end))))
|
||||||
|
|
||||||
(defn pp-seq [y]
|
(defn pp-seq [y]
|
||||||
(def len (length y))
|
(def len (length y))
|
||||||
(if (< len 5)
|
(if (< len 5)
|
||||||
(do
|
(do
|
||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
(when (not= i 0) (buffer-push-string buf " "))
|
(when (not= i 0) (buffer.push-string buf " "))
|
||||||
(recur (get y i))))
|
(recur (get y i))))
|
||||||
(do
|
(do
|
||||||
(buffer-push-string indent " ")
|
(buffer.push-string indent " ")
|
||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
(when (not= i len) (buffer-push-string buf indent))
|
(when (not= i len) (buffer.push-string buf indent))
|
||||||
(recur (get y i)))
|
(recur (get y i)))
|
||||||
(buffer-popn indent 2)
|
(buffer.popn indent 2)
|
||||||
(buffer-push-string buf indent))))
|
(buffer.push-string buf indent))))
|
||||||
|
|
||||||
(defn pp-dict-nested [y]
|
(defn pp-dict-nested [y]
|
||||||
(buffer-push-string indent " ")
|
(buffer.push-string indent " ")
|
||||||
(def ps (sort (pairs y)))
|
(def ps (sort (pairs y)))
|
||||||
(for [i 0 (length ps)]
|
(for [i 0 (length ps)]
|
||||||
(def [k v] (get ps i))
|
(def [k v] (get ps i))
|
||||||
(buffer-push-string buf indent)
|
(buffer.push-string buf indent)
|
||||||
(recur k)
|
(recur k)
|
||||||
(buffer-push-string buf " ")
|
(buffer.push-string buf " ")
|
||||||
(recur v))
|
(recur v))
|
||||||
(buffer-popn indent 2)
|
(buffer.popn indent 2)
|
||||||
(buffer-push-string buf indent))
|
(buffer.push-string buf indent))
|
||||||
|
|
||||||
(defn pp-dict-simple [y]
|
(defn pp-dict-simple [y]
|
||||||
(def ps (sort (pairs y)))
|
(def ps (sort (pairs y)))
|
||||||
(for [i 0 (length ps)]
|
(for [i 0 (length ps)]
|
||||||
(def [k v] (get ps i))
|
(def [k v] (get ps i))
|
||||||
(if (pos? i) (buffer-push-string buf " "))
|
(if (pos? i) (buffer.push-string buf " "))
|
||||||
(recur k)
|
(recur k)
|
||||||
(buffer-push-string buf " ")
|
(buffer.push-string buf " ")
|
||||||
(recur v)))
|
(recur v)))
|
||||||
|
|
||||||
(defn pp-dict [y]
|
(defn pp-dict [y]
|
||||||
@ -741,12 +741,12 @@ to call on any table. Does not print table prototype information."
|
|||||||
(def p (get printers (type y)))
|
(def p (get printers (type y)))
|
||||||
(if p
|
(if p
|
||||||
(p y)
|
(p y)
|
||||||
(buffer-push-string buf (describe y)))))
|
(buffer.push-string buf (describe y)))))
|
||||||
|
|
||||||
(recur x)
|
(recur x)
|
||||||
(buffer-push-string buf "\n")
|
(buffer.push-string buf "\n")
|
||||||
|
|
||||||
(file-write stdout buf))
|
(file.write stdout buf))
|
||||||
|
|
||||||
###
|
###
|
||||||
###
|
###
|
||||||
@ -762,7 +762,7 @@ to call on any table. Does not print table prototype information."
|
|||||||
(def len (length a))
|
(def len (length a))
|
||||||
(def newa @[])
|
(def newa @[])
|
||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
(array-push newa (macroexpand1 (get a i))))
|
(array.push newa (macroexpand1 (get a i))))
|
||||||
newa)
|
newa)
|
||||||
|
|
||||||
(defn dotable [t]
|
(defn dotable [t]
|
||||||
@ -776,14 +776,14 @@ to call on any table. Does not print table prototype information."
|
|||||||
(defn expandlast [t]
|
(defn expandlast [t]
|
||||||
(def len (length t))
|
(def len (length t))
|
||||||
(def last (get t (- len 1)))
|
(def last (get t (- len 1)))
|
||||||
(tuple-append (tuple-slice t 0 -2) (macroexpand1 last)))
|
(tuple.append (tuple.slice t 0 -2) (macroexpand1 last)))
|
||||||
|
|
||||||
(defn expandall [t]
|
(defn expandall [t]
|
||||||
(def args (doarray (tuple-slice t 1)))
|
(def args (doarray (tuple.slice t 1)))
|
||||||
(apply tuple (get t 0) args))
|
(apply tuple (get t 0) args))
|
||||||
|
|
||||||
(defn expandfn [t]
|
(defn expandfn [t]
|
||||||
(def args (doarray (tuple-slice t 2)))
|
(def args (doarray (tuple.slice t 2)))
|
||||||
(apply tuple 'fn (get t 1) args))
|
(apply tuple 'fn (get t 1) args))
|
||||||
|
|
||||||
(def specs {
|
(def specs {
|
||||||
@ -806,7 +806,7 @@ to call on any table. Does not print table prototype information."
|
|||||||
(def m? (get entry :macro))
|
(def m? (get entry :macro))
|
||||||
(cond
|
(cond
|
||||||
s (s t)
|
s (s t)
|
||||||
m? (apply1 m (tuple-slice t 1))
|
m? (apply1 m (tuple.slice t 1))
|
||||||
(apply1 tuple (doarray t))))
|
(apply1 tuple (doarray t))))
|
||||||
|
|
||||||
(defn doarray* [a]
|
(defn doarray* [a]
|
||||||
@ -815,13 +815,13 @@ to call on any table. Does not print table prototype information."
|
|||||||
|
|
||||||
(defn dotable* [t]
|
(defn dotable* [t]
|
||||||
(def res (dotable t))
|
(def res (dotable t))
|
||||||
(if (= (table-to-struct res) (table-to-struct t)) t res))
|
(if (= (table.to-struct res) (table.to-struct t)) t res))
|
||||||
|
|
||||||
(def ux (ast-unwrap1 x))
|
(def ux (ast.unwrap1 x))
|
||||||
(switch (type ux)
|
(switch (type ux)
|
||||||
:tuple (dotup ux)
|
:tuple (dotup ux)
|
||||||
:array (doarray* ux)
|
:array (doarray* ux)
|
||||||
:struct (table-to-struct (dotable ux))
|
:struct (table.to-struct (dotable ux))
|
||||||
:table (dotable* ux)
|
:table (dotable* ux)
|
||||||
ux))
|
ux))
|
||||||
|
|
||||||
@ -846,7 +846,7 @@ to call on any table. Does not print table prototype information."
|
|||||||
|
|
||||||
(defn make-env [parent]
|
(defn make-env [parent]
|
||||||
(def parent (if parent parent _env))
|
(def parent (if parent parent _env))
|
||||||
(def newenv (setproto @{} parent))
|
(def newenv (table.setproto @{} parent))
|
||||||
(put newenv '_env @{:value newenv :private true})
|
(put newenv '_env @{:value newenv :private true})
|
||||||
newenv)
|
newenv)
|
||||||
|
|
||||||
@ -868,14 +868,14 @@ onvalue."
|
|||||||
(var going true)
|
(var going true)
|
||||||
|
|
||||||
# The parser object
|
# The parser object
|
||||||
(def p (parser 1))
|
(def p (parser.make 1))
|
||||||
|
|
||||||
# Fiber stream of characters
|
# Fiber stream of characters
|
||||||
(def chars (coro
|
(def chars (coro
|
||||||
(def buf @"")
|
(def buf @"")
|
||||||
(var len 1)
|
(var len 1)
|
||||||
(while (< 0 len)
|
(while (< 0 len)
|
||||||
(buffer-clear buf)
|
(buffer.clear buf)
|
||||||
(chunks buf p)
|
(chunks buf p)
|
||||||
(:= len (length buf))
|
(:= len (length buf))
|
||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
@ -885,14 +885,14 @@ onvalue."
|
|||||||
# Fiber stream of values
|
# Fiber stream of values
|
||||||
(def vals (coro
|
(def vals (coro
|
||||||
(while going
|
(while going
|
||||||
(switch (parser-status p)
|
(switch (parser.status p)
|
||||||
:full (yield (parser-produce p))
|
:full (yield (parser.produce p))
|
||||||
:error (onerr "parse" (parser-error p))
|
:error (onerr "parse" (parser.error p))
|
||||||
(switch (fiber-status chars)
|
(switch (fiber.status chars)
|
||||||
:new (parser-byte p (resume chars))
|
:new (parser.byte p (resume chars))
|
||||||
:pending (parser-byte p (resume chars))
|
:pending (parser.byte p (resume chars))
|
||||||
(:= going false))))
|
(:= going false))))
|
||||||
(when (not= :root (parser-status p))
|
(when (not= :root (parser.status p))
|
||||||
(onerr "parse" "unexpected end of source"))))
|
(onerr "parse" "unexpected end of source"))))
|
||||||
|
|
||||||
# Evaluate 1 source form
|
# Evaluate 1 source form
|
||||||
@ -907,7 +907,7 @@ onvalue."
|
|||||||
(onerr "compile" (get res :error))))))
|
(onerr "compile" (get res :error))))))
|
||||||
(def res (resume f))
|
(def res (resume f))
|
||||||
(if good
|
(if good
|
||||||
(if (= (fiber-status f) :error)
|
(if (= (fiber.status f) :error)
|
||||||
(onerr "runtime" res f)
|
(onerr "runtime" res f)
|
||||||
(if going (onvalue res)))))
|
(if going (onvalue res)))))
|
||||||
|
|
||||||
@ -921,10 +921,10 @@ onvalue."
|
|||||||
|
|
||||||
(defn default-error-handler
|
(defn default-error-handler
|
||||||
[t x f]
|
[t x f]
|
||||||
(file-write stdout (string t " error: "))
|
(file.write stdout (string t " error: "))
|
||||||
(pp x)
|
(pp x)
|
||||||
(when f
|
(when f
|
||||||
(def st (fiber-stack f))
|
(def st (fiber.stack f))
|
||||||
(def len (length st))
|
(def len (length st))
|
||||||
(for [i 0 len]
|
(for [i 0 len]
|
||||||
(def {
|
(def {
|
||||||
@ -934,13 +934,13 @@ onvalue."
|
|||||||
:c c
|
:c c
|
||||||
:name name
|
:name name
|
||||||
} (get st i))
|
} (get st i))
|
||||||
(file-write stdout " in")
|
(file.write stdout " in")
|
||||||
(when c (file-write stdout " cfunction"))
|
(when c (file.write stdout " cfunction"))
|
||||||
(when name (file-write stdout (string " " name)))
|
(when name (file.write stdout (string " " name)))
|
||||||
(when func (file-write stdout (string " " func)))
|
(when func (file.write stdout (string " " func)))
|
||||||
(when pc (file-write stdout (string " (pc=" pc ")")))
|
(when pc (file.write stdout (string " (pc=" pc ")")))
|
||||||
(when tail (file-write stdout " (tailcall)"))
|
(when tail (file.write stdout " (tailcall)"))
|
||||||
(file-write stdout "\n"))))
|
(file.write stdout "\n"))))
|
||||||
|
|
||||||
(defn eval
|
(defn eval
|
||||||
"Evaluates a string in the current environment. If more control over the
|
"Evaluates a string in the current environment. If more control over the
|
||||||
@ -951,7 +951,7 @@ environment is needed, use run-context."
|
|||||||
(def ret state)
|
(def ret state)
|
||||||
(:= state nil)
|
(:= state nil)
|
||||||
(if ret
|
(if ret
|
||||||
(buffer-push-string buf ret)))
|
(buffer.push-string buf ret)))
|
||||||
(var returnval nil)
|
(var returnval nil)
|
||||||
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler)
|
(run-context *env* chunks (fn [x] (:= returnval x)) default-error-handler)
|
||||||
returnval)
|
returnval)
|
||||||
@ -965,17 +965,17 @@ environment is needed, use run-context."
|
|||||||
(def check (get cache path))
|
(def check (get cache path))
|
||||||
(if check check (do
|
(if check check (do
|
||||||
(if (or
|
(if (or
|
||||||
(= ".so" (string-slice path -3 -1))
|
(= ".so" (string.slice path -3 -1))
|
||||||
(= ".dll" (string-slice path -4 -1)))
|
(= ".dll" (string.slice path -4 -1)))
|
||||||
((native path))
|
((native path))
|
||||||
(do
|
(do
|
||||||
(def newenv (make-env))
|
(def newenv (make-env))
|
||||||
(put cache path newenv)
|
(put cache path newenv)
|
||||||
(put loading path true)
|
(put loading path true)
|
||||||
(def f (file-open path))
|
(def f (file.open path))
|
||||||
(defn chunks [buf] (file-read f 1024 buf))
|
(defn chunks [buf] (file.read f 1024 buf))
|
||||||
(run-context newenv chunks identity default-error-handler)
|
(run-context newenv chunks identity default-error-handler)
|
||||||
(file-close f)
|
(file.close f)
|
||||||
(put loading path nil)
|
(put loading path nil)
|
||||||
newenv)))))))
|
newenv)))))))
|
||||||
|
|
||||||
@ -1000,7 +1000,7 @@ environment is needed, use run-context."
|
|||||||
get a chunk of source code. Should return nil for end of file."
|
get a chunk of source code. Should return nil for end of file."
|
||||||
(def newenv (make-env))
|
(def newenv (make-env))
|
||||||
(default getchunk (fn [buf]
|
(default getchunk (fn [buf]
|
||||||
(file-read stdin :line buf)))
|
(file.read stdin :line buf)))
|
||||||
(default onvalue (fn [x]
|
(default onvalue (fn [x]
|
||||||
(put newenv '_ @{:value x})
|
(put newenv '_ @{:value x})
|
||||||
(pp x)))
|
(pp x)))
|
||||||
|
@ -45,12 +45,10 @@ static const DstReg cfuns[] = {
|
|||||||
{"scan-real", dst_core_scanreal},
|
{"scan-real", dst_core_scanreal},
|
||||||
{"tuple", dst_core_tuple},
|
{"tuple", dst_core_tuple},
|
||||||
{"struct", dst_core_struct},
|
{"struct", dst_core_struct},
|
||||||
|
{"fiber", dst_core_fiber},
|
||||||
{"buffer", dst_core_buffer},
|
{"buffer", dst_core_buffer},
|
||||||
{"gensym", dst_core_gensym},
|
{"gensym", dst_core_gensym},
|
||||||
{"get", dst_core_get},
|
{"get", dst_core_get},
|
||||||
{"rawget", dst_core_rawget},
|
|
||||||
{"getproto", dst_core_getproto},
|
|
||||||
{"setproto", dst_core_setproto},
|
|
||||||
{"put", dst_core_put},
|
{"put", dst_core_put},
|
||||||
{"length", dst_core_length},
|
{"length", dst_core_length},
|
||||||
{"gccollect", dst_core_gccollect},
|
{"gccollect", dst_core_gccollect},
|
||||||
@ -59,7 +57,7 @@ static const DstReg cfuns[] = {
|
|||||||
{"type", dst_core_type},
|
{"type", dst_core_type},
|
||||||
{"next", dst_core_next},
|
{"next", dst_core_next},
|
||||||
{"hash", dst_core_hash},
|
{"hash", dst_core_hash},
|
||||||
{"string-slice", dst_core_string_slice},
|
{"string.slice", dst_core_string_slice},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -219,13 +219,13 @@ static int cfun_concat(DstArgs args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"array-pop", cfun_pop},
|
{"array.pop", cfun_pop},
|
||||||
{"array-peek", cfun_peek},
|
{"array.peek", cfun_peek},
|
||||||
{"array-push", cfun_push},
|
{"array.push", cfun_push},
|
||||||
{"array-setcount", cfun_setcount},
|
{"array.setcount", cfun_setcount},
|
||||||
{"array-ensure", cfun_ensure},
|
{"array.ensure", cfun_ensure},
|
||||||
{"array-slice", cfun_slice},
|
{"array.slice", cfun_slice},
|
||||||
{"array-concat", cfun_concat},
|
{"array.concat", cfun_concat},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -258,12 +258,12 @@ static int cfun_slice(DstArgs args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"buffer-push-byte", cfun_u8},
|
{"buffer.push-byte", cfun_u8},
|
||||||
{"buffer-push-integer", cfun_int},
|
{"buffer.push-integer", cfun_int},
|
||||||
{"buffer-push-string", cfun_chars},
|
{"buffer.push-string", cfun_chars},
|
||||||
{"buffer-popn", cfun_popn},
|
{"buffer.popn", cfun_popn},
|
||||||
{"buffer-clear", cfun_clear},
|
{"buffer.clear", cfun_clear},
|
||||||
{"buffer-slice", cfun_slice},
|
{"buffer.slice", cfun_slice},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -202,6 +202,14 @@ int dst_core_struct(DstArgs args) {
|
|||||||
return dst_return(args, dst_wrap_struct(dst_struct_end(st)));
|
return dst_return(args, dst_wrap_struct(dst_struct_end(st)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dst_core_fiber(DstArgs args) {
|
||||||
|
DstFiber *fiber;
|
||||||
|
dst_fixarity(args, 1);
|
||||||
|
dst_check(args, 0, DST_FUNCTION);
|
||||||
|
fiber = dst_fiber(dst_unwrap_function(args.v[0]), 64);
|
||||||
|
return dst_return(args, dst_wrap_fiber(fiber));
|
||||||
|
}
|
||||||
|
|
||||||
int dst_core_gensym(DstArgs args) {
|
int dst_core_gensym(DstArgs args) {
|
||||||
dst_maxarity(args, 1);
|
dst_maxarity(args, 1);
|
||||||
if (args.n == 0) {
|
if (args.n == 0) {
|
||||||
@ -230,32 +238,6 @@ int dst_core_get(DstArgs args) {
|
|||||||
return dst_return(args, ds);
|
return dst_return(args, ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dst_core_rawget(DstArgs args) {
|
|
||||||
dst_fixarity(args, 2);
|
|
||||||
dst_check(args, 0, DST_TABLE);
|
|
||||||
return dst_return(args, dst_table_rawget(dst_unwrap_table(args.v[0]), args.v[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
int dst_core_getproto(DstArgs args) {
|
|
||||||
DstTable *t;
|
|
||||||
dst_fixarity(args, 1);
|
|
||||||
dst_check(args, 0, DST_TABLE);
|
|
||||||
t = dst_unwrap_table(args.v[0]);
|
|
||||||
return dst_return(args, t->proto
|
|
||||||
? dst_wrap_table(t->proto)
|
|
||||||
: dst_wrap_nil());
|
|
||||||
}
|
|
||||||
|
|
||||||
int dst_core_setproto(DstArgs args) {
|
|
||||||
dst_fixarity(args, 2);
|
|
||||||
dst_check(args, 0, DST_TABLE);
|
|
||||||
dst_checkmany(args, 1, DST_TFLAG_TABLE | DST_TFLAG_NIL);
|
|
||||||
dst_unwrap_table(args.v[0])->proto = dst_checktype(args.v[1], DST_TABLE)
|
|
||||||
? dst_unwrap_table(args.v[1])
|
|
||||||
: NULL;
|
|
||||||
return dst_return(args, args.v[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int dst_core_put(DstArgs args) {
|
int dst_core_put(DstArgs args) {
|
||||||
Dst ds, key, value;
|
Dst ds, key, value;
|
||||||
DstArgs subargs = args;
|
DstArgs subargs = args;
|
||||||
|
@ -257,14 +257,6 @@ void dst_fiber_popframe(DstFiber *fiber) {
|
|||||||
|
|
||||||
/* CFuns */
|
/* CFuns */
|
||||||
|
|
||||||
static int cfun_fiber(DstArgs args) {
|
|
||||||
DstFiber *fiber;
|
|
||||||
dst_fixarity(args, 1);
|
|
||||||
dst_check(args, 0, DST_FUNCTION);
|
|
||||||
fiber = dst_fiber(dst_unwrap_function(args.v[0]), 64);
|
|
||||||
return dst_return(args, dst_wrap_fiber(fiber));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cfun_status(DstArgs args) {
|
static int cfun_status(DstArgs args) {
|
||||||
const char *status = "";
|
const char *status = "";
|
||||||
dst_fixarity(args, 1);
|
dst_fixarity(args, 1);
|
||||||
@ -346,9 +338,8 @@ static int cfun_stack(DstArgs args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"fiber", cfun_fiber},
|
{"fiber.status", cfun_status},
|
||||||
{"fiber-status", cfun_status},
|
{"fiber.stack", cfun_stack},
|
||||||
{"fiber-stack", cfun_stack},
|
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -298,12 +298,12 @@ static int dst_io_fseek(DstArgs args) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"file-open", dst_io_fopen},
|
{"file.open", dst_io_fopen},
|
||||||
{"file-close", dst_io_fclose},
|
{"file.close", dst_io_fclose},
|
||||||
{"file-read", dst_io_fread},
|
{"file.read", dst_io_fread},
|
||||||
{"file-write", dst_io_fwrite},
|
{"file.write", dst_io_fwrite},
|
||||||
{"file-flush", dst_io_fflush},
|
{"file.flush", dst_io_fflush},
|
||||||
{"file-seek", dst_io_fseek},
|
{"file.seek", dst_io_fseek},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,10 +86,10 @@ static int os_exit(DstArgs args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"os-execute", os_execute},
|
{"os.execute", os_execute},
|
||||||
{"os-exit", os_exit},
|
{"os.exit", os_exit},
|
||||||
{"os-getenv", os_getenv},
|
{"os.getenv", os_getenv},
|
||||||
{"os-setenv", os_setenv},
|
{"os.setenv", os_setenv},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ const uint8_t *dst_cstring(const char *str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Temporary buffer size */
|
/* Temporary buffer size */
|
||||||
#define BUFSIZE 36
|
#define BUFSIZE 64
|
||||||
|
|
||||||
static int32_t real_to_string_impl(uint8_t *buf, double x) {
|
static int32_t real_to_string_impl(uint8_t *buf, double x) {
|
||||||
/* Use 16 decimal places to ignore one ulp errors for now */
|
/* Use 16 decimal places to ignore one ulp errors for now */
|
||||||
@ -175,7 +175,8 @@ static int32_t string_description_impl(uint8_t *buf, const char *title, void *po
|
|||||||
|
|
||||||
pbuf.p = pointer;
|
pbuf.p = pointer;
|
||||||
*c++ = '<';
|
*c++ = '<';
|
||||||
for (i = 0; title[i] && i < 12; ++i)
|
/* Maximum of 32 bytes for abstract type name */
|
||||||
|
for (i = 0; title[i] && i < 32; ++i)
|
||||||
*c++ = ((uint8_t *)title) [i];
|
*c++ = ((uint8_t *)title) [i];
|
||||||
*c++ = ' ';
|
*c++ = ' ';
|
||||||
*c++ = '0';
|
*c++ = '0';
|
||||||
|
@ -235,6 +235,26 @@ void dst_table_merge_struct(DstTable *table, const DstKV *other) {
|
|||||||
dst_table_mergekv(table, other, dst_struct_capacity(other));
|
dst_table_mergekv(table, other, dst_struct_capacity(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cfun_getproto(DstArgs args) {
|
||||||
|
DstTable *t;
|
||||||
|
dst_fixarity(args, 1);
|
||||||
|
dst_check(args, 0, DST_TABLE);
|
||||||
|
t = dst_unwrap_table(args.v[0]);
|
||||||
|
return dst_return(args, t->proto
|
||||||
|
? dst_wrap_table(t->proto)
|
||||||
|
: dst_wrap_nil());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cfun_setproto(DstArgs args) {
|
||||||
|
dst_fixarity(args, 2);
|
||||||
|
dst_check(args, 0, DST_TABLE);
|
||||||
|
dst_checkmany(args, 1, DST_TFLAG_TABLE | DST_TFLAG_NIL);
|
||||||
|
dst_unwrap_table(args.v[0])->proto = dst_checktype(args.v[1], DST_TABLE)
|
||||||
|
? dst_unwrap_table(args.v[1])
|
||||||
|
: NULL;
|
||||||
|
return dst_return(args, args.v[0]);
|
||||||
|
}
|
||||||
|
|
||||||
static int cfun_tostruct(DstArgs args) {
|
static int cfun_tostruct(DstArgs args) {
|
||||||
DstTable *t;
|
DstTable *t;
|
||||||
dst_fixarity(args, 1);
|
dst_fixarity(args, 1);
|
||||||
@ -242,8 +262,17 @@ static int cfun_tostruct(DstArgs args) {
|
|||||||
return dst_return(args, dst_wrap_struct(dst_table_to_struct(t)));
|
return dst_return(args, dst_wrap_struct(dst_table_to_struct(t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cfun_rawget(DstArgs args) {
|
||||||
|
dst_fixarity(args, 2);
|
||||||
|
dst_check(args, 0, DST_TABLE);
|
||||||
|
return dst_return(args, dst_table_rawget(dst_unwrap_table(args.v[0]), args.v[1]));
|
||||||
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"table-to-struct", cfun_tostruct},
|
{"table.to-struct", cfun_tostruct},
|
||||||
|
{"table.getproto", cfun_getproto},
|
||||||
|
{"table.setproto", cfun_setproto},
|
||||||
|
{"table.rawget", cfun_rawget},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,8 +152,8 @@ static int cfun_append(DstArgs args) {
|
|||||||
/* Load the tuple module */
|
/* Load the tuple module */
|
||||||
int dst_lib_tuple(DstArgs args) {
|
int dst_lib_tuple(DstArgs args) {
|
||||||
DstTable *env = dst_env_arg(args);
|
DstTable *env = dst_env_arg(args);
|
||||||
dst_env_def(env, "tuple-slice", dst_wrap_cfunction(cfun_slice));
|
dst_env_def(env, "tuple.slice", dst_wrap_cfunction(cfun_slice));
|
||||||
dst_env_def(env, "tuple-append", dst_wrap_cfunction(cfun_append));
|
dst_env_def(env, "tuple.append", dst_wrap_cfunction(cfun_append));
|
||||||
dst_env_def(env, "tuple-prepend", dst_wrap_cfunction(cfun_prepend));
|
dst_env_def(env, "tuple.prepend", dst_wrap_cfunction(cfun_prepend));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -92,13 +92,11 @@ int dst_core_tuple(DstArgs args);
|
|||||||
int dst_core_array(DstArgs args);
|
int dst_core_array(DstArgs args);
|
||||||
int dst_core_table(DstArgs args);
|
int dst_core_table(DstArgs args);
|
||||||
int dst_core_struct(DstArgs args);
|
int dst_core_struct(DstArgs args);
|
||||||
|
int dst_core_fiber(DstArgs args);
|
||||||
int dst_core_buffer(DstArgs args);
|
int dst_core_buffer(DstArgs args);
|
||||||
int dst_core_gensym(DstArgs args);
|
int dst_core_gensym(DstArgs args);
|
||||||
int dst_core_length(DstArgs args);
|
int dst_core_length(DstArgs args);
|
||||||
int dst_core_get(DstArgs args);
|
int dst_core_get(DstArgs args);
|
||||||
int dst_core_rawget(DstArgs args);
|
|
||||||
int dst_core_getproto(DstArgs args);
|
|
||||||
int dst_core_setproto(DstArgs args);
|
|
||||||
int dst_core_put(DstArgs args);
|
int dst_core_put(DstArgs args);
|
||||||
int dst_core_type(DstArgs args);
|
int dst_core_type(DstArgs args);
|
||||||
int dst_core_next(DstArgs args);
|
int dst_core_next(DstArgs args);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
(do
|
(do
|
||||||
|
|
||||||
(var *should-repl* :private false)
|
(var *should-repl* :private false)
|
||||||
(var *no-file* :private true)
|
(var *no-file* :private true)
|
||||||
(var *raw-stdin* :private false)
|
(var *raw-stdin* :private false)
|
||||||
|
|
||||||
# Flag handlers
|
# Flag handlers
|
||||||
(def handlers :private {
|
(def handlers :private {
|
||||||
"h" (fn []
|
"h" (fn []
|
||||||
(print "usage: " (get args 0) " [options] scripts...")
|
(print "usage: " (get args 0) " [options] scripts...")
|
||||||
(print "Options are:")
|
(print "Options are:")
|
||||||
@ -14,9 +14,9 @@
|
|||||||
(print " -s Use raw stdin instead of getline like functionality")
|
(print " -s Use raw stdin instead of getline like functionality")
|
||||||
(print " -e Execute a string of dst")
|
(print " -e Execute a string of dst")
|
||||||
(print " -r Enter the repl after running all scripts")
|
(print " -r Enter the repl after running all scripts")
|
||||||
(os-exit 0)
|
(os.exit 0)
|
||||||
1)
|
1)
|
||||||
"v" (fn [] (print VERSION) (os-exit 0) 1)
|
"v" (fn [] (print VERSION) (os.exit 0) 1)
|
||||||
"s" (fn [] (:= *raw-stdin* true) (:= *should-repl* true) 1)
|
"s" (fn [] (:= *raw-stdin* true) (:= *should-repl* true) 1)
|
||||||
"r" (fn [] (:= *should-repl* true) 1)
|
"r" (fn [] (:= *should-repl* true) 1)
|
||||||
"e" (fn [i]
|
"e" (fn [i]
|
||||||
@ -25,27 +25,27 @@
|
|||||||
2)
|
2)
|
||||||
})
|
})
|
||||||
|
|
||||||
(defn- dohandler [n i]
|
(defn- dohandler [n i]
|
||||||
(def h (get handlers n))
|
(def h (get handlers n))
|
||||||
(if h (h i) (print "unknown flag -" n)))
|
(if h (h i) (print "unknown flag -" n)))
|
||||||
|
|
||||||
# Process arguments
|
# Process arguments
|
||||||
(var i 1)
|
(var i 1)
|
||||||
(def lenargs (length args))
|
(def lenargs (length args))
|
||||||
(while (< i lenargs)
|
(while (< i lenargs)
|
||||||
(def arg (get args i))
|
(def arg (get args i))
|
||||||
(if (= "-" (string-slice arg 0 1))
|
(if (= "-" (string.slice arg 0 1))
|
||||||
(+= i (dohandler (string-slice arg 1 2) i))
|
(+= i (dohandler (string.slice arg 1 2) i))
|
||||||
(do
|
(do
|
||||||
(:= *no-file* false)
|
(:= *no-file* false)
|
||||||
(import arg)
|
(import arg)
|
||||||
(++ i))))
|
(++ i))))
|
||||||
|
|
||||||
(when (or *should-repl* *no-file*)
|
(when (or *should-repl* *no-file*)
|
||||||
(if *raw-stdin*
|
(if *raw-stdin*
|
||||||
(repl nil identity)
|
(repl nil identity)
|
||||||
(do
|
(do
|
||||||
(print (string "Dst " VERSION " Copyright (C) 2017-2018 Calvin Rose"))
|
(print (string "Dst " VERSION " Copyright (C) 2017-2018 Calvin Rose"))
|
||||||
(repl (fn [buf p]
|
(repl (fn [buf p]
|
||||||
(def prompt (string (parser-state p) "> "))
|
(def prompt (string (parser.state p) "> "))
|
||||||
(getline prompt buf)))))))
|
(getline prompt buf)))))))
|
||||||
|
@ -769,18 +769,18 @@ static int cfun_node(DstArgs args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"parser", cfun_parser},
|
{"parser.make", cfun_parser},
|
||||||
{"parser-produce", cfun_produce},
|
{"parser.produce", cfun_produce},
|
||||||
{"parser-consume", cfun_consume},
|
{"parser.consume", cfun_consume},
|
||||||
{"parser-byte", cfun_byte},
|
{"parser.byte", cfun_byte},
|
||||||
{"parser-error", cfun_error},
|
{"parser.error", cfun_error},
|
||||||
{"parser-status", cfun_status},
|
{"parser.status", cfun_status},
|
||||||
{"parser-flush", cfun_flush},
|
{"parser.flush", cfun_flush},
|
||||||
{"parser-state", cfun_state},
|
{"parser.state", cfun_state},
|
||||||
{"ast-unwrap", cfun_unwrap},
|
{"ast.unwrap", cfun_unwrap},
|
||||||
{"ast-unwrap1", cfun_unwrap1},
|
{"ast.unwrap1", cfun_unwrap1},
|
||||||
{"ast-wrap", cfun_wrap},
|
{"ast.wrap", cfun_wrap},
|
||||||
{"ast-node", cfun_node},
|
{"ast.node", cfun_node},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,4 +19,4 @@
|
|||||||
(defn end-suite []
|
(defn end-suite []
|
||||||
(print "\nTest suite " suite-num " finished.")
|
(print "\nTest suite " suite-num " finished.")
|
||||||
(print num-tests-passed " of " num-tests-run " tests passed.\n")
|
(print num-tests-passed " of " num-tests-run " tests passed.\n")
|
||||||
(if (not= num-tests-passed num-tests-run) (os-exit 1)))
|
(if (not= num-tests-passed num-tests-run) (os.exit 1)))
|
||||||
|
@ -151,7 +151,7 @@
|
|||||||
(def afiber-result (resume afiber "world!"))
|
(def afiber-result (resume afiber "world!"))
|
||||||
|
|
||||||
(assert (= afiber-result "hello, world!") "fiber error result")
|
(assert (= afiber-result "hello, world!") "fiber error result")
|
||||||
(assert (= (fiber-status afiber) :error) "fiber error status")
|
(assert (= (fiber.status afiber) :error) "fiber error status")
|
||||||
|
|
||||||
# yield tests
|
# yield tests
|
||||||
|
|
||||||
@ -160,7 +160,7 @@
|
|||||||
(assert (= 1 (resume t)) "initial transfer to new fiber")
|
(assert (= 1 (resume t)) "initial transfer to new fiber")
|
||||||
(assert (= 2 (resume t)) "second transfer to fiber")
|
(assert (= 2 (resume t)) "second transfer to fiber")
|
||||||
(assert (= 3 (resume t)) "return from fiber")
|
(assert (= 3 (resume t)) "return from fiber")
|
||||||
(assert (= (fiber-status t) :dead) "finished fiber is dead")
|
(assert (= (fiber.status t) :dead) "finished fiber is dead")
|
||||||
|
|
||||||
# Var arg tests
|
# Var arg tests
|
||||||
|
|
||||||
@ -216,17 +216,17 @@
|
|||||||
(def xi (get xs i))
|
(def xi (get xs i))
|
||||||
(def yj (get ys j))
|
(def yj (get ys j))
|
||||||
(if (< xi yj)
|
(if (< xi yj)
|
||||||
(do (array-push ret xi) (:= i (+ i 1)))
|
(do (array.push ret xi) (:= i (+ i 1)))
|
||||||
(do (array-push ret yj) (:= j (+ j 1)))))
|
(do (array.push ret yj) (:= j (+ j 1)))))
|
||||||
# Push rest of xs
|
# Push rest of xs
|
||||||
(while (< i xlen)
|
(while (< i xlen)
|
||||||
(def xi (get xs i))
|
(def xi (get xs i))
|
||||||
(array-push ret xi)
|
(array.push ret xi)
|
||||||
(:= i (+ i 1)))
|
(:= i (+ i 1)))
|
||||||
# Push rest of ys
|
# Push rest of ys
|
||||||
(while (< j ylen)
|
(while (< j ylen)
|
||||||
(def yj (get ys j))
|
(def yj (get ys j))
|
||||||
(array-push ret yj)
|
(array.push ret yj)
|
||||||
(:= j (+ j 1)))
|
(:= j (+ j 1)))
|
||||||
ret))
|
ret))
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
:childprop 456
|
:childprop 456
|
||||||
})
|
})
|
||||||
|
|
||||||
(setproto childtab roottab)
|
(table.setproto childtab roottab)
|
||||||
|
|
||||||
(assert (= 123 (get roottab :parentprop)), "table get 1")
|
(assert (= 123 (get roottab :parentprop)), "table get 1")
|
||||||
(assert (= 123 (get childtab :parentprop)), "table get proto")
|
(assert (= 123 (get childtab :parentprop)), "table get proto")
|
||||||
|
Loading…
Reference in New Issue
Block a user