Compare commits
No commits in common. "9d798e5e586a99fbe8787d6d1160b72919e304df" and "e4a948ba947da01b95e329cd797f3e13975faf08" have entirely different histories.
9d798e5e58
...
e4a948ba94
|
@ -1,133 +1,133 @@
|
|||
& the very base: know something's type
|
||||
fn type {
|
||||
"Returns a keyword representing the type of the value passed in."
|
||||
(x) -> base :type (x)
|
||||
}
|
||||
& fn type {
|
||||
& "Returns a keyword representing the type of the value passed in."
|
||||
& (x) -> base :type (x)
|
||||
& }
|
||||
|
||||
& & some helper type functions
|
||||
fn coll? {
|
||||
"Returns true if a value is a collection: dict, list, tuple, or set."
|
||||
(coll as :dict) -> true
|
||||
(coll as :list) -> true
|
||||
(coll as :tuple) -> true
|
||||
& (coll as :set) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn coll? {
|
||||
& "Returns true if a value is a collection: dict, list, tuple, or set."
|
||||
& (coll as :dict) -> true
|
||||
& (coll as :list) -> true
|
||||
& (coll as :tuple) -> true
|
||||
& & (coll as :set) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn ordered? {
|
||||
"Returns true if a value is an indexed collection: list or tuple."
|
||||
(coll as :list) -> true
|
||||
(coll as :tuple) -> true
|
||||
(coll as :string) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn ordered? {
|
||||
& "Returns true if a value is an indexed collection: list or tuple."
|
||||
& (coll as :list) -> true
|
||||
& (coll as :tuple) -> true
|
||||
& (coll as :string) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn assoc? {
|
||||
"Returns true if a value is an associative collection: a dict or a pkg."
|
||||
(d as :dict) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn assoc? {
|
||||
& "Returns true if a value is an associative collection: a dict or a pkg."
|
||||
& (d as :dict) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
& &&& nil: working with nothing
|
||||
|
||||
fn nil? {
|
||||
"Returns true if a value is nil."
|
||||
(nil) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn nil? {
|
||||
& "Returns true if a value is nil."
|
||||
& (nil) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn some? {
|
||||
"Returns true if a value is not nil."
|
||||
(nil) -> false
|
||||
(_) -> true
|
||||
}
|
||||
& fn some? {
|
||||
& "Returns true if a value is not nil."
|
||||
& (nil) -> false
|
||||
& (_) -> true
|
||||
& }
|
||||
|
||||
fn some {
|
||||
"Takes a possibly nil value and a default value. Returns the value if it's not nil, returns the default if it's nil."
|
||||
(nil, default) -> default
|
||||
(value, _) -> value
|
||||
}
|
||||
& fn some {
|
||||
& "Takes a possibly nil value and a default value. Returns the value if it's not nil, returns the default if it's nil."
|
||||
& (nil, default) -> default
|
||||
& (value, _) -> value
|
||||
& }
|
||||
|
||||
& ...and if two things are the same
|
||||
fn eq? {
|
||||
"Returns true if all arguments have the same value."
|
||||
(x) -> true
|
||||
& (x) -> true
|
||||
(x, y) -> base :eq? (x, y)
|
||||
(x, y, ...zs) -> if eq? (x, y)
|
||||
then loop (y, zs) with {
|
||||
(a, [b]) -> and (eq? (a, x), eq? (b, x))
|
||||
(a, [b, ...cs]) -> if eq? (a, x)
|
||||
then recur (b, cs)
|
||||
else false
|
||||
}
|
||||
else false
|
||||
& (x, y, ...zs) -> if eq? (x, y)
|
||||
& then loop (y, zs) with {
|
||||
& (a, []) -> eq? (a, x)
|
||||
& (a, [b, ...cs]) -> if eq? (a, x)
|
||||
& then recur (b, cs)
|
||||
& else false
|
||||
& }
|
||||
& else false
|
||||
}
|
||||
|
||||
& &&& true & false: boolean logic (part the first)
|
||||
fn bool? {
|
||||
"Returns true if a value is of type :boolean."
|
||||
(false) -> true
|
||||
(true) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn bool? {
|
||||
& "Returns true if a value is of type :boolean."
|
||||
& (false) -> true
|
||||
& (true) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn true? {
|
||||
"Returns true if a value is boolean `true`. Useful to distinguish between `true` and anything else."
|
||||
(true) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn true? {
|
||||
& "Returns true if a value is boolean `true`. Useful to distinguish between `true` and anything else."
|
||||
& (true) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn false? {
|
||||
"Returns `true` if a value is `false`, otherwise returns `false`. Useful to distinguish between `false` and `nil`."
|
||||
(false) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn false? {
|
||||
& "Returns `true` if a value is `false`, otherwise returns `false`. Useful to distinguish between `false` and `nil`."
|
||||
& (false) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn bool {
|
||||
"Returns false if a value is nil or false, otherwise returns true."
|
||||
(nil) -> false
|
||||
(false) -> false
|
||||
(_) -> true
|
||||
}
|
||||
& fn bool {
|
||||
& "Returns false if a value is nil or false, otherwise returns true."
|
||||
& (nil) -> false
|
||||
& (false) -> false
|
||||
& (_) -> true
|
||||
& }
|
||||
|
||||
fn not {
|
||||
"Returns false if a value is truthy, true if a value is falsy."
|
||||
(nil) -> true
|
||||
(false) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn not {
|
||||
& "Returns false if a value is truthy, true if a value is falsy."
|
||||
& (nil) -> true
|
||||
& (false) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
& & tuples: not a lot you can do with them functionally
|
||||
fn tuple? {
|
||||
"Returns true if a value is a tuple."
|
||||
(tuple as :tuple) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn tuple? {
|
||||
& "Returns true if a value is a tuple."
|
||||
& (tuple as :tuple) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
& &&& functions: getting things done
|
||||
fn fn? {
|
||||
"Returns true if an argument is a function."
|
||||
(f as :fn) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn fn? {
|
||||
& "Returns true if an argument is a function."
|
||||
& (f as :fn) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
& what we need for some very basic list manipulation
|
||||
fn first {
|
||||
"Retrieves the first element of an ordered collection--a tuple or a list. If the collection is empty, returns nil."
|
||||
([]) -> nil
|
||||
(()) -> nil
|
||||
& (()) -> nil
|
||||
& ("") -> nil
|
||||
(xs as :list) -> base :first (xs)
|
||||
(xs as :tuple) -> base :first (xs)
|
||||
& (xs as :tuple) -> base :first (xs)
|
||||
& (str as :string) -> base :slice (str, 0, 1)
|
||||
}
|
||||
|
||||
fn rest {
|
||||
"Returns all but the first element of a list or tuple, as a list."
|
||||
([]) -> []
|
||||
(()) -> ()
|
||||
& (()) -> ()
|
||||
(xs as :list) -> base :rest (xs)
|
||||
(xs as :tuple) -> base :rest (xs)
|
||||
& (xs as :tuple) -> base :rest (xs)
|
||||
& (str as :string) -> base :rest (str)
|
||||
}
|
||||
|
||||
|
@ -136,50 +136,50 @@ fn inc {
|
|||
(x as :number) -> base :inc (x)
|
||||
}
|
||||
|
||||
fn dec {
|
||||
"Decrements a number."
|
||||
(x as :number) -> base :dec (x)
|
||||
}
|
||||
& fn dec {
|
||||
& "Decrements a number."
|
||||
& (x as :number) -> base :dec (x)
|
||||
& }
|
||||
|
||||
fn count {
|
||||
"Returns the number of elements in a collection (including string)."
|
||||
(xs as :list) -> base :count (xs)
|
||||
(xs as :tuple) -> base :count (xs)
|
||||
(xs as :dict) -> base :count (xs)
|
||||
(xs as :string) -> base :count (xs)
|
||||
& (xs as :set) -> base :count (xs)
|
||||
}
|
||||
& fn count {
|
||||
& "Returns the number of elements in a collection (including string)."
|
||||
& (xs as :list) -> base :count (xs)
|
||||
& (xs as :tuple) -> base :count (xs)
|
||||
& (xs as :dict) -> base :count (xs)
|
||||
& (xs as :string) -> base :count (xs)
|
||||
& & (xs as :set) -> base :count (xs)
|
||||
& }
|
||||
|
||||
fn empty? {
|
||||
"Returns true if something is empty. Otherwise returns false (including for things that can't logically be empty, like numbers)."
|
||||
([]) -> true
|
||||
(#{}) -> true
|
||||
& (s as :set) -> eq? (s, ${})
|
||||
(()) -> true
|
||||
("") -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn empty? {
|
||||
& "Returns true if something is empty. Otherwise returns false (including for things that can't logically be empty, like numbers)."
|
||||
& ([]) -> true
|
||||
& (#{}) -> true
|
||||
& & (s as :set) -> eq? (s, ${})
|
||||
& (()) -> true
|
||||
& ("") -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn any? {
|
||||
"Returns true if something is not empty, otherwise returns false (including for things that can't be logically full, like numbers)."
|
||||
([...]) -> true
|
||||
(#{...}) -> true
|
||||
& (s as :set) -> not (empty? (s))
|
||||
((...)) -> true
|
||||
(s as :string) -> not (empty? (s))
|
||||
(_) -> false
|
||||
}
|
||||
& fn any? {
|
||||
& "Returns true if something is not empty, otherwise returns false (including for things that can't be logically full, like numbers)."
|
||||
& ([...]) -> true
|
||||
& (#{...}) -> true
|
||||
& & (s as :set) -> not (empty? (s))
|
||||
& ((...)) -> true
|
||||
& (s as :string) -> not (empty? (s))
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn list? {
|
||||
"Returns true if the value is a list."
|
||||
(l as :list) -> true
|
||||
(_) -> false
|
||||
}
|
||||
& fn list? {
|
||||
& "Returns true if the value is a list."
|
||||
& (l as :list) -> true
|
||||
& (_) -> false
|
||||
& }
|
||||
|
||||
fn list {
|
||||
"Takes a value and returns it as a list. For values, it simply wraps them in a list. For collections, conversions are as follows. A tuple->list conversion preservers order and length. Unordered collections do not preserve order: sets and dicts don't have predictable or stable ordering in output. Dicts return lists of (key, value) tuples."
|
||||
(x) -> base :list (x)
|
||||
}
|
||||
& fn list {
|
||||
& "Takes a value and returns it as a list. For values, it simply wraps them in a list. For collections, conversions are as follows. A tuple->list conversion preservers order and length. Unordered collections do not preserve order: sets and dicts don't have predictable or stable ordering in output. Dicts return lists of (key, value) tuples."
|
||||
& (x) -> base :list (x)
|
||||
& }
|
||||
|
||||
fn append {
|
||||
"Adds an element to a list."
|
||||
|
@ -203,58 +203,43 @@ fn fold {
|
|||
}
|
||||
}
|
||||
|
||||
fn foldr {
|
||||
"Folds a list, right-associatively."
|
||||
(f as :fn, []) -> []
|
||||
(f as :fn, xs as :list) -> foldr(f, xs, f ())
|
||||
(f as :fn, [], root) -> []
|
||||
(f as :fn, xs as :list, root) -> loop (root, first (xs), rest (xs)) with {
|
||||
(prev, curr, []) -> f (curr, prev)
|
||||
(prev, curr, remaining) -> recur (
|
||||
f (curr, prev)
|
||||
first (remaining)
|
||||
rest (remaining)
|
||||
)
|
||||
}
|
||||
}
|
||||
& fn map {
|
||||
& "Maps a function over a list: returns a new list with elements that are the result of applying the function to each element in the original list. E.g., `map ([1, 2, 3], inc) &=> [2, 3, 4]`. With one argument, returns a function that is a mapper over lists; with two, it executes the mapping function right away."
|
||||
& & (f as :fn) -> map (f, _)
|
||||
& & (kw as :keyword) -> map (kw, _)
|
||||
& (f as :fn, xs) -> {
|
||||
& fn mapper (prev, curr) -> append (prev, f (curr))
|
||||
& fold (mapper, xs, [])
|
||||
& }
|
||||
& & (kw as :keyword, xs) -> {
|
||||
& & fn mapper (prev, curr) -> append (prev, kw (curr))
|
||||
& & fold (mapper, xs, [])
|
||||
& & }
|
||||
& }
|
||||
|
||||
fn map {
|
||||
"Maps a function over a list: returns a new list with elements that are the result of applying the function to each element in the original list. E.g., `map ([1, 2, 3], inc) &=> [2, 3, 4]`. With one argument, returns a function that is a mapper over lists; with two, it executes the mapping function right away."
|
||||
(f as :fn) -> map (f, _)
|
||||
(kw as :keyword) -> map (kw, _)
|
||||
(f as :fn, xs) -> {
|
||||
fn mapper (prev, curr) -> append (prev, f (curr))
|
||||
fold (mapper, xs, [])
|
||||
}
|
||||
(kw as :keyword, xs) -> {
|
||||
fn mapper (prev, curr) -> append (prev, kw (curr))
|
||||
fold (mapper, xs, [])
|
||||
}
|
||||
}
|
||||
& fn filter {
|
||||
& "Takes a list and a predicate function, and returns a new list with only the items that produce truthy values when the function is called on them. E.g., `filter ([1, 2, 3, 4], odd?) &=> [1, 3]`."
|
||||
& (p? as :fn) -> filter (p?, _)
|
||||
& (p? as :fn, xs) -> {
|
||||
& fn filterer (filtered, x) -> if p? (x)
|
||||
& then append (filtered, x)
|
||||
& else filtered
|
||||
& fold (filterer, xs, [])
|
||||
& }
|
||||
& }
|
||||
|
||||
fn filter {
|
||||
"Takes a list and a predicate function, and returns a new list with only the items that produce truthy values when the function is called on them. E.g., `filter ([1, 2, 3, 4], odd?) &=> [1, 3]`."
|
||||
(p? as :fn) -> filter (p?, _)
|
||||
(p? as :fn, xs) -> {
|
||||
fn filterer (filtered, x) -> if p? (x)
|
||||
then append (filtered, x)
|
||||
else filtered
|
||||
fold (filterer, xs, [])
|
||||
}
|
||||
}
|
||||
& fn keep {
|
||||
& "Takes a list and returns a new list with any `nil` values omitted."
|
||||
& (xs) -> filter (some?, xs)
|
||||
& }
|
||||
|
||||
fn keep {
|
||||
"Takes a list and returns a new list with any `nil` values omitted."
|
||||
(xs) -> filter (some?, xs)
|
||||
}
|
||||
|
||||
fn concat {
|
||||
"Combines two lists, strings, or sets."
|
||||
(x as :string, y as :string) -> "{x}{y}"
|
||||
(xs as :list, ys as :list) -> base :concat (xs, ys)
|
||||
& (xs as :set, ys as :set) -> base :concat (xs, ys)
|
||||
(xs, ys, ...zs) -> fold (concat, zs, concat (xs, ys))
|
||||
}
|
||||
& fn concat {
|
||||
& "Combines two lists, strings, or sets."
|
||||
& (x as :string, y as :string) -> "{x}{y}"
|
||||
& (xs as :list, ys as :list) -> base :concat (xs, ys)
|
||||
& & (xs as :set, ys as :set) -> base :concat (xs, ys)
|
||||
& (xs, ys, ...zs) -> fold (concat, zs, concat (xs, ys))
|
||||
& }
|
||||
|
||||
fn contains? {
|
||||
"Returns true if a set or list contains a value."
|
||||
|
@ -267,92 +252,44 @@ fn contains? {
|
|||
}
|
||||
}
|
||||
|
||||
fn print! {
|
||||
"Sends a text representation of Ludus values to the console."
|
||||
(...args) -> {
|
||||
base :print! (args)
|
||||
:ok
|
||||
}
|
||||
}
|
||||
|
||||
fn show {
|
||||
"Returns a text representation of a Ludus value as a string."
|
||||
(x) -> base :show (x)
|
||||
}
|
||||
|
||||
fn report! {
|
||||
"Prints a value, then returns it."
|
||||
(x) -> {
|
||||
print! (x)
|
||||
x
|
||||
}
|
||||
(msg as :string, x) -> {
|
||||
print! (concat ("{msg} ", show (x)))
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
fn doc! {
|
||||
"Prints the documentation of a function to the console."
|
||||
(f as :fn) -> do f > base :doc! > print!
|
||||
(_) -> :none
|
||||
}
|
||||
|
||||
&&& strings: harder than they look!
|
||||
fn string? {
|
||||
"Returns true if a value is a string."
|
||||
(x as :string) -> true
|
||||
(_) -> false
|
||||
}
|
||||
|
||||
fn string {
|
||||
"Converts a value to a string by using `show`. If it is a string, returns it unharmed. Use this to build up strings of different kinds of values."
|
||||
(x as :string) -> x
|
||||
(x) -> show (x)
|
||||
(x, ...xs) -> loop (string (x), xs) with {
|
||||
(out, [y]) -> concat (out, show (y))
|
||||
(out, [y, ...ys]) -> recur (concat (out, show (y)), ys)
|
||||
}
|
||||
fn add {
|
||||
() -> 0
|
||||
(x) -> x
|
||||
(x, y) -> base :add (x, y)
|
||||
}
|
||||
|
||||
#{
|
||||
type
|
||||
coll?
|
||||
ordered?
|
||||
assoc?
|
||||
nil?
|
||||
some?
|
||||
some
|
||||
& type
|
||||
& coll?
|
||||
& ordered?
|
||||
& assoc?
|
||||
& nil?
|
||||
& some?
|
||||
& some
|
||||
eq?
|
||||
bool?
|
||||
true?
|
||||
false?
|
||||
bool
|
||||
not
|
||||
tuple?
|
||||
fn?
|
||||
& bool?
|
||||
& true?
|
||||
& false?
|
||||
& bool
|
||||
& not
|
||||
& tuple?
|
||||
& fn?
|
||||
first
|
||||
rest
|
||||
inc
|
||||
dec
|
||||
count
|
||||
empty?
|
||||
any?
|
||||
list?
|
||||
list
|
||||
first
|
||||
fold
|
||||
foldr
|
||||
append
|
||||
map
|
||||
filter
|
||||
keep
|
||||
concat
|
||||
contains?
|
||||
print!
|
||||
show
|
||||
report!
|
||||
doc!
|
||||
string
|
||||
string?
|
||||
& inc
|
||||
& dec
|
||||
& count
|
||||
& empty?
|
||||
& any?
|
||||
& list?
|
||||
& list
|
||||
& first
|
||||
& fold
|
||||
& append
|
||||
& map
|
||||
& filter
|
||||
& keep
|
||||
& concat
|
||||
& contains?
|
||||
add
|
||||
}
|
||||
|
|
29
sandbox.ld
29
sandbox.ld
|
@ -1,4 +1,31 @@
|
|||
|
||||
let test = 3
|
||||
|
||||
let quux = loop ([1, 2]) with {
|
||||
([]) -> false
|
||||
([x]) -> eq? (x, test)
|
||||
([x, ...xs]) -> if eq? (x, test)
|
||||
then :yes
|
||||
else recur (xs)
|
||||
}
|
||||
|
||||
|
||||
let foo = :bar
|
||||
|
||||
fn not {
|
||||
(false) -> true
|
||||
(nil) -> true
|
||||
(_) -> false
|
||||
}
|
||||
|
||||
let frob = loop ([1, 2, 3]) with {
|
||||
([]) -> false
|
||||
([y]) -> eq? (y, test)
|
||||
([y, ...ys]) -> if not (eq? (y, test))
|
||||
then recur (ys)
|
||||
else true
|
||||
}
|
||||
|
||||
[quux, frob]
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -310,11 +310,6 @@ impl<'a> Compiler<'a> {
|
|||
self.stack_depth += 1;
|
||||
}
|
||||
|
||||
fn duplicate(&mut self) {
|
||||
self.emit_op(Op::Duplicate);
|
||||
self.stack_depth += 1;
|
||||
}
|
||||
|
||||
fn pop(&mut self) {
|
||||
self.emit_op(Op::Pop);
|
||||
self.stack_depth -= 1;
|
||||
|
@ -433,6 +428,7 @@ impl<'a> Compiler<'a> {
|
|||
self.tail_pos = false;
|
||||
// increase the scope
|
||||
self.enter_scope();
|
||||
// self.scope_depth += 1;
|
||||
// stash the stack depth
|
||||
let stack_depth = self.stack_depth;
|
||||
// evaluate all the lines but the last
|
||||
|
@ -453,6 +449,7 @@ impl<'a> Compiler<'a> {
|
|||
// we do this by pretending it's a binding
|
||||
(Let(patt, expr), _) => {
|
||||
// self.match_depth = 0;
|
||||
// self.emit_op(Op::ResetMatch);
|
||||
self.visit(expr);
|
||||
let expr_pos = self.stack_depth - 1;
|
||||
self.report_ast("let binding: matching".to_string(), patt);
|
||||
|
@ -470,20 +467,28 @@ impl<'a> Compiler<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// we've made a new value, so increase the stack level in the compiler
|
||||
self.stack_depth += 1;
|
||||
|
||||
// store the value in the return register
|
||||
// self.emit_op(Op::Store);
|
||||
self.store();
|
||||
|
||||
// reset the scope
|
||||
self.leave_scope();
|
||||
// self.scope_depth -= 1;
|
||||
// while let Some(binding) = self.bindings.last() {
|
||||
// if binding.depth > self.scope_depth {
|
||||
// self.bindings.pop();
|
||||
// } else {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// reset the stack
|
||||
self.report_depth("leaving block before pop");
|
||||
self.msg(format!(
|
||||
"popping back from {} to {}",
|
||||
self.stack_depth, stack_depth,
|
||||
));
|
||||
self.pop_n(self.stack_depth - stack_depth);
|
||||
self.pop_n(self.stack_depth - stack_depth - 1);
|
||||
// load the value from the return register
|
||||
self.load();
|
||||
// self.emit_op(Op::Load);
|
||||
}
|
||||
If(cond, then, r#else) => {
|
||||
let tail_pos = self.tail_pos;
|
||||
|
@ -858,44 +863,42 @@ impl<'a> Compiler<'a> {
|
|||
self.stack_depth -= 1;
|
||||
}
|
||||
(Or, Arguments(args)) => {
|
||||
let stack_depth = self.stack_depth;
|
||||
let mut jump_idxes = vec![];
|
||||
if !args.is_empty() {
|
||||
let mut args = args.iter().rev();
|
||||
let last = args.next().unwrap();
|
||||
for arg in args.rev() {
|
||||
for arg in args {
|
||||
self.visit(arg);
|
||||
self.duplicate();
|
||||
self.emit_op(Op::Stash);
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfTrue));
|
||||
self.pop();
|
||||
}
|
||||
self.visit(last);
|
||||
for idx in jump_idxes {
|
||||
self.patch_jump(idx, self.len() - idx - 3);
|
||||
self.patch_jump(idx, self.len() - idx);
|
||||
}
|
||||
// self.emit_op(Op::Load);
|
||||
self.load();
|
||||
} else {
|
||||
self.emit_op(Op::False);
|
||||
self.stack_depth += 1;
|
||||
}
|
||||
self.stack_depth = stack_depth + 1;
|
||||
}
|
||||
(And, Arguments(args)) => {
|
||||
let stack_depth = self.stack_depth;
|
||||
let mut jump_idxes = vec![];
|
||||
if !args.is_empty() {
|
||||
let mut args = args.iter().rev();
|
||||
let last = args.next().unwrap();
|
||||
for arg in args.rev() {
|
||||
for arg in args {
|
||||
self.visit(arg);
|
||||
self.duplicate();
|
||||
self.emit_op(Op::Stash);
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfFalse));
|
||||
self.pop();
|
||||
}
|
||||
self.visit(last);
|
||||
for idx in jump_idxes {
|
||||
self.patch_jump(idx, self.len() - idx - 3);
|
||||
self.patch_jump(idx, self.len() - idx);
|
||||
}
|
||||
// self.emit_op(Op::Load);
|
||||
self.load();
|
||||
} else {
|
||||
self.emit_op(Op::True);
|
||||
self.stack_depth += 1;
|
||||
}
|
||||
self.stack_depth = stack_depth + 1;
|
||||
}
|
||||
(Word(fn_name), Arguments(args)) => {
|
||||
self.report_depth_str(format!("calling function {fn_name}"));
|
||||
|
@ -948,12 +951,13 @@ impl<'a> Compiler<'a> {
|
|||
self.stack_depth -= 1;
|
||||
}
|
||||
Arguments(args) => {
|
||||
self.store();
|
||||
self.emit_op(Op::Stash);
|
||||
self.pop();
|
||||
let arity = args.len();
|
||||
for arg in args {
|
||||
self.visit(arg);
|
||||
}
|
||||
self.load();
|
||||
self.emit_op(Op::Load);
|
||||
if tail_pos && i == num_rest_terms - 1 {
|
||||
self.emit_op(Op::TailCall)
|
||||
} else {
|
||||
|
@ -1145,6 +1149,7 @@ impl<'a> Compiler<'a> {
|
|||
}
|
||||
compiler.tail_pos = true;
|
||||
compiler.visit(clause_body);
|
||||
// compiler.emit_op(Op::Store);
|
||||
compiler.store();
|
||||
compiler.scope_depth -= 1;
|
||||
while let Some(binding) = compiler.bindings.last() {
|
||||
|
@ -1386,6 +1391,7 @@ impl<'a> Compiler<'a> {
|
|||
let allocated = Value::String(Rc::new(str.clone()));
|
||||
self.emit_constant(allocated);
|
||||
self.emit_op(Op::ConcatStrings);
|
||||
self.stack_depth -= 1;
|
||||
}
|
||||
StringPart::Word(word) => {
|
||||
self.resolve_binding(word);
|
||||
|
@ -1393,7 +1399,6 @@ impl<'a> Compiler<'a> {
|
|||
self.emit_op(Op::ConcatStrings);
|
||||
}
|
||||
}
|
||||
self.stack_depth -= 1;
|
||||
}
|
||||
}
|
||||
Do(terms) => {
|
||||
|
|
|
@ -284,7 +284,7 @@ impl<'a> Validator<'a> {
|
|||
// check arity against fn info if first term is word and second term is args
|
||||
Synthetic(first, second, rest) => {
|
||||
match (&first.0, &second.0) {
|
||||
(Ast::And, Ast::Arguments(_)) | (Ast::Or, Ast::Arguments(_)) => {
|
||||
(Ast::And, Ast::Arguments(_)) | (Ast::Or, Ast::Tuple(_)) => {
|
||||
self.visit(second.as_ref())
|
||||
}
|
||||
(Ast::Word(_), Ast::Keyword(_)) => self.visit(first.as_ref()),
|
||||
|
|
Loading…
Reference in New Issue
Block a user