Spelling
This commit is contained in:
20
bf.kp
20
bf.kp
@@ -5,25 +5,25 @@
|
|||||||
(def! make-atom (fn* (x) [x]))
|
(def! make-atom (fn* (x) [x]))
|
||||||
(def! set-atom! (fn* (x y) (set-nth! x 0 y)))
|
(def! set-atom! (fn* (x y) (set-nth! x 0 y)))
|
||||||
(def! get-atom (fn* (x) (nth x 0)))
|
(def! get-atom (fn* (x) (nth x 0)))
|
||||||
(add_grammer_rule 'form ["@" 'form] (fn* (_ x) `(get-atom ~x)))
|
(add_grammar_rule 'form ["@" 'form] (fn* (_ x) `(get-atom ~x)))
|
||||||
|
|
||||||
; Now begin by defining our BF syntax & semantics
|
; Now begin by defining our BF syntax & semantics
|
||||||
; Define our tokens as BF atoms
|
; Define our tokens as BF atoms
|
||||||
(add_grammer_rule 'bfs_atom ["<"] (fn* (_) '(set-atom! cursor (- @cursor 1))))
|
(add_grammar_rule 'bfs_atom ["<"] (fn* (_) '(set-atom! cursor (- @cursor 1))))
|
||||||
(add_grammer_rule 'bfs_atom [">"] (fn* (_) '(set-atom! cursor (+ @cursor 1))))
|
(add_grammar_rule 'bfs_atom [">"] (fn* (_) '(set-atom! cursor (+ @cursor 1))))
|
||||||
(add_grammer_rule 'bfs_atom ["\\+"] (fn* (_) '(set-nth! tape @cursor (+ (nth tape @cursor) 1))))
|
(add_grammar_rule 'bfs_atom ["\\+"] (fn* (_) '(set-nth! tape @cursor (+ (nth tape @cursor) 1))))
|
||||||
(add_grammer_rule 'bfs_atom ["-"] (fn* (_) '(set-nth! tape @cursor (- (nth tape @cursor) 1))))
|
(add_grammar_rule 'bfs_atom ["-"] (fn* (_) '(set-nth! tape @cursor (- (nth tape @cursor) 1))))
|
||||||
(add_grammer_rule 'bfs_atom [","] (fn* (_) '(let* (value (nth input @inptr))
|
(add_grammar_rule 'bfs_atom [","] (fn* (_) '(let* (value (nth input @inptr))
|
||||||
(do (set-atom! inptr (+ 1 @inptr))
|
(do (set-atom! inptr (+ 1 @inptr))
|
||||||
(set-nth! tape @cursor value)))))
|
(set-nth! tape @cursor value)))))
|
||||||
(add_grammer_rule 'bfs_atom ["."] (fn* (_) '(set-atom! output (cons (nth tape @cursor) @output))))
|
(add_grammar_rule 'bfs_atom ["."] (fn* (_) '(set-atom! output (cons (nth tape @cursor) @output))))
|
||||||
|
|
||||||
; Define strings of BF atoms
|
; Define strings of BF atoms
|
||||||
(add_grammer_rule 'bfs ['bfs_atom *] (fn* (x) x))
|
(add_grammar_rule 'bfs ['bfs_atom *] (fn* (x) x))
|
||||||
|
|
||||||
; Add loop as an atom
|
; Add loop as an atom
|
||||||
; (note that closure cannot yet close over itself by value, so we pass it in)
|
; (note that closure cannot yet close over itself by value, so we pass it in)
|
||||||
(add_grammer_rule 'bfs_atom ["\\[" 'bfs "]"] (fn* (_ x _)
|
(add_grammar_rule 'bfs_atom ["\\[" 'bfs "]"] (fn* (_ x _)
|
||||||
`(let* (f (fn* (f)
|
`(let* (f (fn* (f)
|
||||||
(if (= 0 (nth tape @cursor))
|
(if (= 0 (nth tape @cursor))
|
||||||
nil
|
nil
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
; For now, stick BFS rule inside an unambigious BFS block
|
; For now, stick BFS rule inside an unambigious BFS block
|
||||||
; Also add setup code
|
; Also add setup code
|
||||||
(add_grammer_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"]
|
(add_grammar_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"]
|
||||||
(fn* (_ _ _ _ x _ _)
|
(fn* (_ _ _ _ x _ _)
|
||||||
`(fn* (input)
|
`(fn* (input)
|
||||||
(let* (
|
(let* (
|
||||||
|
|||||||
74
fungll.krak
74
fungll.krak
@@ -283,21 +283,21 @@ fun bs(nonterminal: int, rule_idx: int, idx_into_rule: int, left: int, pivot: in
|
|||||||
var to_ret.construct(nonterminal, rule_idx, idx_into_rule, left, pivot, right): BS
|
var to_ret.construct(nonterminal, rule_idx, idx_into_rule, left, pivot, right): BS
|
||||||
return to_ret
|
return to_ret
|
||||||
}
|
}
|
||||||
/*fun fungll<T,K>(grammer: ref Grammer<T,K>, start_symbol: *char, input: ref str): set<BS> {*/
|
/*fun fungll<T,K>(grammar: ref Grammer<T,K>, start_symbol: *char, input: ref str): set<BS> {*/
|
||||||
/*return fungll(grammer, str(start_symbol), input)*/
|
/*return fungll(grammar, str(start_symbol), input)*/
|
||||||
/*}*/
|
/*}*/
|
||||||
/*fun fungll<T,K>(grammer: ref Grammer<T,K>, start_symbol: str, input: ref str): set<BS> {*/
|
/*fun fungll<T,K>(grammar: ref Grammer<T,K>, start_symbol: str, input: ref str): set<BS> {*/
|
||||||
/*return fungll(grammer, -1*(grammer.nonterminal_funs.find(start_symbol)+1), input)*/
|
/*return fungll(grammar, -1*(grammar.nonterminal_funs.find(start_symbol)+1), input)*/
|
||||||
/*}*/
|
/*}*/
|
||||||
fun fungll<T,K>(grammer: ref Grammer<T,K>, start_symbol: int, input: ref str): set<BS> {
|
fun fungll<T,K>(grammar: ref Grammer<T,K>, start_symbol: int, input: ref str): set<BS> {
|
||||||
var R = descend(grammer, start_symbol, 0)
|
var R = descend(grammar, start_symbol, 0)
|
||||||
var U = set<Descriptor>()
|
var U = set<Descriptor>()
|
||||||
var G = map<pair<int, int>, set<Pending>>()
|
var G = map<pair<int, int>, set<Pending>>()
|
||||||
var P = map<pair<int,int>, set<int>>()
|
var P = map<pair<int,int>, set<int>>()
|
||||||
var Y = set<BS>()
|
var Y = set<BS>()
|
||||||
while R.size() != 0 {
|
while R.size() != 0 {
|
||||||
var d = R.pop()
|
var d = R.pop()
|
||||||
var it = process(grammer, input, d, G, P)
|
var it = process(grammar, input, d, G, P)
|
||||||
var Rp = it.first.first
|
var Rp = it.first.first
|
||||||
var Yp = it.first.second
|
var Yp = it.first.second
|
||||||
var Gp = it.second
|
var Gp = it.second
|
||||||
@@ -325,21 +325,21 @@ fun fungll<T,K>(grammer: ref Grammer<T,K>, start_symbol: int, input: ref str): s
|
|||||||
}
|
}
|
||||||
return Y
|
return Y
|
||||||
}
|
}
|
||||||
fun descend<T,K>(grammer: ref Grammer<T,K>, symbol: int, l: int): set<Descriptor> {
|
fun descend<T,K>(grammar: ref Grammer<T,K>, symbol: int, l: int): set<Descriptor> {
|
||||||
var to_ret = set<Descriptor>()
|
var to_ret = set<Descriptor>()
|
||||||
for (var rhs = 0; rhs < grammer.get_nonterminal_rules(symbol).size; rhs++;)
|
for (var rhs = 0; rhs < grammar.get_nonterminal_rules(symbol).size; rhs++;)
|
||||||
to_ret.add(descriptor(symbol, rhs, 0, l, l))
|
to_ret.add(descriptor(symbol, rhs, 0, l, l))
|
||||||
return to_ret
|
return to_ret
|
||||||
}
|
}
|
||||||
fun process<T,K>(grammer: ref Grammer<T,K>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
|
fun process<T,K>(grammar: ref Grammer<T,K>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
|
||||||
// if at end / end is emptystr
|
// if at end / end is emptystr
|
||||||
if descript.idx_into_rule == grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx].size {
|
if descript.idx_into_rule == grammar.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx].size {
|
||||||
return process_e(grammer, descript, G, P)
|
return process_e(grammar, descript, G, P)
|
||||||
} else {
|
} else {
|
||||||
return process_symbol(grammer, input, descript, G, P)
|
return process_symbol(grammar, input, descript, G, P)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun process_e<T,K>(grammer: ref Grammer<T,K>, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
|
fun process_e<T,K>(grammar: ref Grammer<T,K>, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
|
||||||
var nonterminal: int
|
var nonterminal: int
|
||||||
var rule_idx: int
|
var rule_idx: int
|
||||||
var left: int
|
var left: int
|
||||||
@@ -351,29 +351,29 @@ fun process_e<T,K>(grammer: ref Grammer<T,K>, descript: Descriptor, G: ref map<p
|
|||||||
var it = ascend(l,K,k)
|
var it = ascend(l,K,k)
|
||||||
var R = it.first
|
var R = it.first
|
||||||
var Y = it.second
|
var Y = it.second
|
||||||
if grammer.get_nonterminal_rules(X)[descript.rule_idx].size == 0 {
|
if grammar.get_nonterminal_rules(X)[descript.rule_idx].size == 0 {
|
||||||
Y.add(bs(X,descript.rule_idx, 0, l, l, l))
|
Y.add(bs(X,descript.rule_idx, 0, l, l, l))
|
||||||
}
|
}
|
||||||
return make_triple(make_pair(R,Y), map<pair<int, int>, set<Pending>>(), map(make_pair(X,l), set(k)))
|
return make_triple(make_pair(R,Y), map<pair<int, int>, set<Pending>>(), map(make_pair(X,l), set(k)))
|
||||||
}
|
}
|
||||||
fun process_symbol<T,K>(grammer: ref Grammer<T,K>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
|
fun process_symbol<T,K>(grammar: ref Grammer<T,K>, input: ref str, descript: Descriptor, G: ref map<pair<int, int>, set<Pending>>, P: ref map<pair<int,int>, set<int>>): triple<pair<set<Descriptor>, set<BS>>, map<pair<int, int>, set<Pending>>, map<pair<int,int>, set<int>>> {
|
||||||
var s = grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]
|
var s = grammar.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]
|
||||||
var k = descript.pivot
|
var k = descript.pivot
|
||||||
var R = P.get_with_default(make_pair(s,k), set<int>())
|
var R = P.get_with_default(make_pair(s,k), set<int>())
|
||||||
var Gp = map(make_pair(s,k), set(pending(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left)))
|
var Gp = map(make_pair(s,k), set(pending(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left)))
|
||||||
if grammer.is_terminal(s) {
|
if grammar.is_terminal(s) {
|
||||||
return make_triple(matc(grammer,input,descript), map<pair<int,int>, set<Pending>>(), map<pair<int,int>, set<int>>())
|
return make_triple(matc(grammar,input,descript), map<pair<int,int>, set<Pending>>(), map<pair<int,int>, set<int>>())
|
||||||
} else if R.size() == 0 { // s in N
|
} else if R.size() == 0 { // s in N
|
||||||
return make_triple(make_pair(descend(grammer,s,k), set<BS>()), Gp, map<pair<int,int>, set<int>>())
|
return make_triple(make_pair(descend(grammar,s,k), set<BS>()), Gp, map<pair<int,int>, set<int>>())
|
||||||
} else { // s in N and R != set()
|
} else { // s in N and R != set()
|
||||||
return make_triple(skip(k,pending(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left), R), Gp, map<pair<int,int>, set<int>>())
|
return make_triple(skip(k,pending(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left), R), Gp, map<pair<int,int>, set<int>>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun matc<T,K>(grammer: ref Grammer<T,K>, input: ref str, descript: Descriptor): pair<set<Descriptor>, set<BS>> {
|
fun matc<T,K>(grammar: ref Grammer<T,K>, input: ref str, descript: Descriptor): pair<set<Descriptor>, set<BS>> {
|
||||||
/*println("trying to match " + grammer.to_string(grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]))*/
|
/*println("trying to match " + grammar.to_string(grammar.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]))*/
|
||||||
var match_length = grammer.match_terminal(grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule], input, descript.pivot)
|
var match_length = grammar.match_terminal(grammar.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule], input, descript.pivot)
|
||||||
if match_length > 0 {
|
if match_length > 0 {
|
||||||
/*println("matched " + grammer.to_string(grammer.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]))*/
|
/*println("matched " + grammar.to_string(grammar.get_nonterminal_rules(descript.nonterminal)[descript.rule_idx][descript.idx_into_rule]))*/
|
||||||
return make_pair(set(descriptor(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left, descript.pivot+match_length)), set(bs(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left, descript.pivot, descript.pivot+match_length)))
|
return make_pair(set(descriptor(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left, descript.pivot+match_length)), set(bs(descript.nonterminal, descript.rule_idx, descript.idx_into_rule+1, descript.left, descript.pivot, descript.pivot+match_length)))
|
||||||
} else {
|
} else {
|
||||||
return make_pair(set<Descriptor>(), set<BS>())
|
return make_pair(set<Descriptor>(), set<BS>())
|
||||||
@@ -395,31 +395,31 @@ fun nmatch(k:int, K: ref set<Pending>, R: ref set<int>): pair<set<Descriptor>, s
|
|||||||
return make_pair(Rp,Y)
|
return make_pair(Rp,Y)
|
||||||
}
|
}
|
||||||
/*fun main(argc: int, argv: **char): int {*/
|
/*fun main(argc: int, argv: **char): int {*/
|
||||||
/*var grammer.construct(): Grammer<int>*/
|
/*var grammar.construct(): Grammer<int>*/
|
||||||
/*var Number = grammer.add_new_nonterminal("Number", vec(grammer.add_terminal("[0-9]+", fun(input: ref str, l: int, r: int): int { return string_to_num<int>(input.slice(l,r)); })), fun(i: ref vec<int>): int { return i[0]; })*/
|
/*var Number = grammar.add_new_nonterminal("Number", vec(grammar.add_terminal("[0-9]+", fun(input: ref str, l: int, r: int): int { return string_to_num<int>(input.slice(l,r)); })), fun(i: ref vec<int>): int { return i[0]; })*/
|
||||||
|
|
||||||
/*var mult = grammer.add_terminal("\\*", fun(input: ref str, l: int, r: int): int { return 1; })*/
|
/*var mult = grammar.add_terminal("\\*", fun(input: ref str, l: int, r: int): int { return 1; })*/
|
||||||
/*var Factor = grammer.add_new_nonterminal("Factor", vec(Number), fun(i: ref vec<int>): int { return i[0]; })*/
|
/*var Factor = grammar.add_new_nonterminal("Factor", vec(Number), fun(i: ref vec<int>): int { return i[0]; })*/
|
||||||
/*grammer.add_to_nonterminal(Factor, vec(Factor, mult, Number), fun(i: ref vec<int>): int { return i[0]*i[2]; })*/
|
/*grammar.add_to_nonterminal(Factor, vec(Factor, mult, Number), fun(i: ref vec<int>): int { return i[0]*i[2]; })*/
|
||||||
|
|
||||||
/*var add = grammer.add_terminal("\\+", fun(input: ref str, l: int, r: int): int { return 1; })*/
|
/*var add = grammar.add_terminal("\\+", fun(input: ref str, l: int, r: int): int { return 1; })*/
|
||||||
/*var Term = grammer.add_new_nonterminal("Term", vec(Factor), fun(i: ref vec<int>): int { return i[0]; })*/
|
/*var Term = grammar.add_new_nonterminal("Term", vec(Factor), fun(i: ref vec<int>): int { return i[0]; })*/
|
||||||
/*grammer.add_to_nonterminal(Term, vec(Term, add, Factor), fun(i: ref vec<int>): int { return i[0]+i[2]; })*/
|
/*grammar.add_to_nonterminal(Term, vec(Term, add, Factor), fun(i: ref vec<int>): int { return i[0]+i[2]; })*/
|
||||||
|
|
||||||
/*grammer.set_start_symbol(Term)*/
|
/*grammar.set_start_symbol(Term)*/
|
||||||
|
|
||||||
/*var input = str("1+23*44")*/
|
/*var input = str("1+23*44")*/
|
||||||
/*var BSR = fungll(grammer, input)*/
|
/*var BSR = fungll(grammar, input)*/
|
||||||
|
|
||||||
|
|
||||||
/*println(str("length of BSR is: ") + BSR.size())*/
|
/*println(str("length of BSR is: ") + BSR.size())*/
|
||||||
/*for (var i = 0; i < BSR.data.size; i++;) {*/
|
/*for (var i = 0; i < BSR.data.size; i++;) {*/
|
||||||
/*var BS = BSR.data[i]*/
|
/*var BS = BSR.data[i]*/
|
||||||
/*println(str() + i + ": " + grammer.to_string(BSR.data[i]))*/
|
/*println(str() + i + ": " + grammar.to_string(BSR.data[i]))*/
|
||||||
/*}*/
|
/*}*/
|
||||||
|
|
||||||
/*var res = grammer.eval_BSR(input, BSR)*/
|
/*var res = grammar.eval_BSR(input, BSR)*/
|
||||||
/*println(str("result of grammer.eval_BSR(fungll(grammer, ") + input + ")) = " + res)*/
|
/*println(str("result of grammar.eval_BSR(fungll(grammar, ") + input + ")) = " + res)*/
|
||||||
|
|
||||||
/*return 0*/
|
/*return 0*/
|
||||||
/*}*/
|
/*}*/
|
||||||
|
|||||||
295
index.html
295
index.html
@@ -3,266 +3,121 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
h1, h2 ,h3 { line-height:1.2; }
|
body{
|
||||||
body {
|
margin:1em auto;
|
||||||
max-width: 45em;
|
padding:0 .62em;
|
||||||
margin: 1em auto;
|
font:1.2em/1.62 sans-serif;
|
||||||
padding: 0 .62em;
|
|
||||||
font: 1.2em/1.62 sans-serif;
|
|
||||||
}
|
}
|
||||||
|
h1,h2,h3 {
|
||||||
th { text-align: center; }
|
line-height:1.2;
|
||||||
th, td { padding: 0.5em; }
|
}
|
||||||
table, td {
|
@media print{
|
||||||
border: 1px solid #333;
|
body{
|
||||||
text-align: right;
|
max-width:none
|
||||||
}
|
}
|
||||||
thead, tfoot {
|
|
||||||
background-color: #000;
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#hello_editor { height: 7em; width: 70em; }
|
|
||||||
#hello_output { height: 7em; width: 70em; }
|
|
||||||
#method_editor { height: 53em; width: 70em; }
|
|
||||||
#method_output { height: 7em; width: 70em; }
|
|
||||||
#bf_editor { height: 62em; width: 70em; }
|
|
||||||
#bf_output { height: 7em; width: 70em; }
|
|
||||||
#fib_editor { height: 8em; width: 70em; }
|
|
||||||
#fib_output { height: 7em; width: 70em; }
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header><h2>Nathan Braswell's Current Programming Language / Compiler Research</h2></header>
|
<header> <h3>Nathan Braswell's Current Programming Language / Compiler Research</h3> </header>
|
||||||
Repository: <a title="Kraken on GitHub" href="https://github.com/limvot/kraken">https://github.com/limvot/kraken</a>
|
<h4> Current idea:</h4>
|
||||||
<br> <br>
|
|
||||||
<b>Table of Contents:</b> <i>If you're impatient, jump to the code examples!</i>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#concept">Concept</a>
|
<li> Minimal, close to the metal Scheme (operate on words & bytes) as AST / core language
|
||||||
<li><a href="#about">About</a>
|
<li> Full Context-free (and eventually, context sensitive) reader macros using FUN-GLL (<a title="fun-gll paper" href="https://www.sciencedirect.com/science/article/pii/S2590118420300058">paper</a>)
|
||||||
<li><a href="#hello_example">Example: Hello World</a>
|
<li> Implement Type Systems as Macros (<a title="type systems as macros paper 1" href="http://www.ccs.neu.edu/home/stchang/pubs/ckg-popl2017.pdf">paper, up to System Fomega</a>) (<a title="type systems as macros paper 2" href="https://www.ccs.neu.edu/home/stchang/pubs/cbtb-popl2020.pdf">second paper, up to dependent types</a>)
|
||||||
<li><a href="#method_example">Example: Implementing Methods</a>
|
<li> Use above macros to create richer language and embed entire other programming languages for flawless interop/FFI (C, Go, Lua, JS, etc)
|
||||||
<li><a href="#bf_example">Example: Embedding BF</a>
|
<li> Regionalized Value State Dependence Graph as backend-IR, enabling simpler implementations of powerful optimizations (<a title="RSVDG paper" href="https://arxiv.org/pdf/1912.05036.pdf">RSVDG paper</a>)
|
||||||
<li><a href="#benchmarks">Performance Benchmarks</a>
|
|
||||||
<li><a href="#fib_example">Example: Fibonacci</a>
|
|
||||||
<li><a href="#next_steps">Next Steps</a>
|
|
||||||
</ul>
|
</ul>
|
||||||
<a name="concept"/>
|
<h4> Status:</h4>
|
||||||
<h3>Concept:</h3>
|
|
||||||
<ul>
|
|
||||||
<li> Minimal, close to the metal Scheme (operate on words, bytes, vectors) as AST / core language
|
|
||||||
<li> Full Context-free (and eventually, context sensitive) reader macros using FUN-GLL (<a title="fun-gll paper" href="https://www.sciencedirect.com/science/article/pii/S2590118420300058">FUN-GLL paper</a>) to extend language's syntax dynamically
|
|
||||||
<li> Implement Type Systems as Macros (<a title="type systems as macros paper 1" href="http://www.ccs.neu.edu/home/stchang/pubs/ckg-popl2017.pdf">paper, up to System Fω</a>) (<a title="type systems as macros paper 2" href="https://www.ccs.neu.edu/home/stchang/pubs/cbtb-popl2020.pdf">second paper, up to dependent types</a>)
|
|
||||||
<li> Use above macros to create richer language and embed entire other programming languages (syntax, semantics, and type system) for flawless interop/FFI (C, Go, Lua, JS, etc)
|
|
||||||
<li> File is interpreted, and then if "main" exists it is compiled, spidering backwards to referenced functions and data (Allows interpreted code to do metaprogramming, dependency resolution, generate code, etc, which is then compiled)
|
|
||||||
<li> Regionalized Value State Dependence Graph as backend-IR, enabling simpler implementations of powerful optimizations (<a title="RSVDG paper" href="https://arxiv.org/pdf/1912.05036.pdf">RSVDG paper</a>) so that embedded languages have good performance when compiled with little code
|
|
||||||
</ul>
|
|
||||||
<a name="about"/>
|
|
||||||
<h3> About:</h3>
|
|
||||||
<p> Currently, I am bootstrapping this new core Lisp out of my prior compiler for my programming language, Kraken. I have implemented the first version of the FUN-GLL algorithm and have working context-free reader macros. I'll have enough to self-host this core soon, and will then use the more efficent core Lisp implementation to implement the Type Systems as Macros paper and add a type system to the new language.
|
<p> Currently, I am bootstrapping this new core Lisp out of my prior compiler for my programming language, Kraken. I have implemented the first version of the FUN-GLL algorithm and have working context-free reader macros. I'll have enough to self-host this core soon, and will then use the more efficent core Lisp implementation to implement the Type Systems as Macros paper and add a type system to the new language.
|
||||||
<p> The general flow is that the input file is executed with the core Lisp interpreter, and if there is a "main" symbol defined the compiler emits C for that function & all other functions & data that it references. In this way the language supports very powerful meta-programming at compile time, including adding syntax to the language, arbitrary computation, and importing other files, and then compiles into a static executable. The current compiling backend emits C.
|
<p> Below is an example of using the live grammer modification / context-free reader macros to embed the BF language into the core Lisp. The core Lisp implementation has been compiled to WebAssembly and should be able to run in your browser. Feel free to make edits and play around below.
|
||||||
<p> Below are a few examples of using the live grammer modification / context-free reader macros to implement basic methods as well as embed the BF language into the core Lisp. The core Lisp implementation has been compiled to WebAssembly and should be able to run in your browser. Feel free to make edits and play around below.
|
|
||||||
<br>
|
<br>
|
||||||
Note that the current implementation is inefficent, and sometimes has problems running in phone web browsers.
|
<h4>Code:</h4>
|
||||||
<a name="hello_example"/>
|
<textarea id="code" cols=130 rows=30>
|
||||||
<h4>Runnable Example Code:</h4>
|
; Of course
|
||||||
<button onclick="executeKraken(hello_editor.getValue(), 'hello_output')"><b>Run</b></button> <br>
|
|
||||||
<div id="hello_editor">; Of course
|
|
||||||
(println "Hello World")
|
(println "Hello World")
|
||||||
; Just print 3
|
; Just print 3
|
||||||
(println "Math works:" (+ 1 2))
|
(println "Math works:" (+ 1 2))
|
||||||
</div>
|
|
||||||
<h4>Output:</h4>
|
|
||||||
<textarea id="hello_output">Output will appear here</textarea>
|
|
||||||
<a name="method_example"/>
|
|
||||||
<h4>Method Example:</h4>
|
|
||||||
Let's use our meta system (attaching objects to other objects) to implement basic objects/methods.
|
|
||||||
We will attach a vector of alternating symbols / functions (to make this example simple, since maps aren't built in) to our data as the meta, then look up methods on it when we perform a call. The add_grammer_rule function modifies the grammer/parser currently being used to parse the file and operates as a super-powerful reader macro. We use it in this code to add a rule that transforms <pre><code>a.b(c, d)</code></pre> into <pre><code>(method-call a 'b c d)</code></pre> where method-call is the function that looks up the symbol 'b on the meta object attached to a and calls it with the rest of the parameters.
|
|
||||||
<br>
|
|
||||||
<button onclick="executeKraken(method_editor.getValue(), 'method_output')"><b>Run</b></button>
|
|
||||||
<br>
|
|
||||||
<div id="method_editor">; First quick lookup function, since maps are not built in
|
|
||||||
(def! get-value-helper (fn* (dict key idx) (if (>= idx (count dict))
|
|
||||||
nil
|
|
||||||
(if (= key (nth dict idx))
|
|
||||||
(nth dict (+ idx 1))
|
|
||||||
(get-value-helper dict key (+ idx 2))))))
|
|
||||||
(def! get-value (fn* (dict key) (get-value-helper dict key 0)))
|
|
||||||
|
|
||||||
; Our actual method call function
|
; Use the power of GLL reader macros to implement
|
||||||
(def! method-call (fn* (object method & arguments) (let* (method_fn (get-value (meta object) method))
|
; BF support
|
||||||
(if (= method_fn nil)
|
|
||||||
(println "no method " method)
|
|
||||||
(apply method_fn object arguments)))))
|
|
||||||
; Some nice syntatic sugar for method calls
|
|
||||||
(add_grammer_rule 'form ['form "\\." 'atom 'optional_WS "\\(" 'optional_WS 'space_forms 'optional_WS "\\)"]
|
|
||||||
(fn* (o _ m _ _ _ p _ _) `(method-call ~o '~m ,p)))
|
|
||||||
|
|
||||||
; Ok, let's create our object by hand for this example
|
; Utility until we get stdlib & datastructures figured out
|
||||||
(def! actual_obj (with-meta [0] [
|
(def! with_update (fn* [arr idx val]
|
||||||
'inc (fn* (o) (set-nth! o 0 (+ (nth o 0) 1)))
|
(if (= idx 0)
|
||||||
'dec (fn* (o) (set-nth! o 0 (- (nth o 0) 1)))
|
(cons val (rest arr))
|
||||||
'set (fn* (o n) (set-nth! o 0 n))
|
(cons (first arr) (with_update (rest arr) (- idx 1) val)))))
|
||||||
'get (fn* (o) (nth o 0))
|
|
||||||
]))
|
|
||||||
(do
|
|
||||||
; Use our new sugar
|
|
||||||
actual_obj.set(1337)
|
|
||||||
actual_obj.inc()
|
|
||||||
(println "get: " actual_obj.get())
|
|
||||||
actual_obj.dec()
|
|
||||||
(println "get: " actual_obj.get())
|
|
||||||
|
|
||||||
; Use methods directly
|
|
||||||
(method-call actual_obj 'set 654)
|
|
||||||
(method-call actual_obj 'inc)
|
|
||||||
(println "get: " (method-call actual_obj 'get))
|
|
||||||
(method-call actual_obj 'dec)
|
|
||||||
(method-call actual_obj 'dec)
|
|
||||||
(println "get: " (method-call actual_obj 'get))
|
|
||||||
|
|
||||||
nil)
|
|
||||||
</div>
|
|
||||||
<h4>Output: </h4>
|
|
||||||
<textarea id="method_output">Output will appear here</textarea>
|
|
||||||
<a name="bf_example"/>
|
|
||||||
<h4>More Complicated Example: BF as an embedded language</h4>
|
|
||||||
<button onclick="executeKraken(bf_editor.getValue(), 'bf_output')"><b>Run</b></button> <br>
|
|
||||||
<div id="bf_editor">; We don't have atoms built in, mutable vectors
|
|
||||||
; are our base building block. In order to make the
|
|
||||||
; following BF implementation nice, let's add atoms!
|
|
||||||
; They will be implmented as length 1 vectors with nice syntax for deref
|
|
||||||
(def! make-atom (fn* (x) [x]))
|
|
||||||
(def! set-atom! (fn* (x y) (set-nth! x 0 y)))
|
|
||||||
(def! get-atom (fn* (x) (nth x 0)))
|
|
||||||
(add_grammer_rule 'form ["@" 'form] (fn* (_ x) `(get-atom ~x)))
|
|
||||||
|
|
||||||
; Now begin by defining our BF syntax & semantics
|
|
||||||
; Define our tokens as BF atoms
|
; Define our tokens as BF atoms
|
||||||
(add_grammer_rule 'bfs_atom ["<"] (fn* (_) '(set-atom! cursor (- @cursor 1))))
|
(add_grammer_rule 'bfs_atom ["<"] (fn* [xs] (list 'left)))
|
||||||
(add_grammer_rule 'bfs_atom [">"] (fn* (_) '(set-atom! cursor (+ @cursor 1))))
|
(add_grammer_rule 'bfs_atom [">"] (fn* [xs] (list 'right)))
|
||||||
(add_grammer_rule 'bfs_atom ["\\+"] (fn* (_) '(set-nth! tape @cursor (+ (nth tape @cursor) 1))))
|
(add_grammer_rule 'bfs_atom ["\\+"] (fn* [xs] (list 'plus)))
|
||||||
(add_grammer_rule 'bfs_atom ["-"] (fn* (_) '(set-nth! tape @cursor (- (nth tape @cursor) 1))))
|
(add_grammer_rule 'bfs_atom ["-"] (fn* [xs] (list 'minus)))
|
||||||
(add_grammer_rule 'bfs_atom [","] (fn* (_) '(let* (value (nth input @inptr))
|
(add_grammer_rule 'bfs_atom [","] (fn* [xs] (list 'in)))
|
||||||
(do (set-atom! inptr (+ 1 @inptr))
|
(add_grammer_rule 'bfs_atom ["."] (fn* [xs] (list 'out)))
|
||||||
(set-nth! tape @cursor value)))))
|
|
||||||
(add_grammer_rule 'bfs_atom ["."] (fn* (_) '(set-atom! output (cons (nth tape @cursor) @output))))
|
|
||||||
|
|
||||||
; Define strings of BF atoms
|
; Define strings of BF atoms
|
||||||
(add_grammer_rule 'bfs ['bfs_atom *] (fn* (x) x))
|
(add_grammer_rule 'non_empty_bfs_list ['bfs_atom] (fn* [xs] (list (nth xs 0))))
|
||||||
|
(add_grammer_rule 'non_empty_bfs_list ['bfs_atom 'optional_WS 'non_empty_bfs_list] (fn* [xs] (cons (nth xs 0) (nth xs 2))))
|
||||||
|
(add_grammer_rule 'bfs_list [] (fn* [xs] xs))
|
||||||
|
(add_grammer_rule 'bfs_list ['non_empty_bfs_list] (fn* [xs] (nth xs 0)))
|
||||||
|
|
||||||
; Add loop as an atom
|
; Add loop as an atom
|
||||||
; (note that closure cannot yet close over itself by value, so we pass it in)
|
(add_grammer_rule 'bfs_atom ["\\[" 'bfs_list "]"] (fn* [xs]
|
||||||
(add_grammer_rule 'bfs_atom ["\\[" 'bfs "]"] (fn* (_ x _)
|
`(let* (f (fn* []
|
||||||
`(let* (f (fn* (f)
|
(if (= 0 (nth (deref arr) (deref ptr)))
|
||||||
(if (= 0 (nth tape @cursor))
|
|
||||||
nil
|
nil
|
||||||
(do ,x (f f)))))
|
(do ,(nth xs 1) (f)))))
|
||||||
(f f))))
|
(f))))
|
||||||
|
|
||||||
|
; Top level BFS rule
|
||||||
|
(add_grammer_rule 'bfs ['bfs_list] (fn* [xs] (nth xs 0)))
|
||||||
|
|
||||||
; For now, stick BFS rule inside an unambigious BFS block
|
; For now, stick BFS rule inside an unambigious BFS block
|
||||||
; Also add setup code
|
; and add compilation/implementation
|
||||||
|
; Note that this compilation into the underlying Lisp
|
||||||
|
; happens at macro evaluation time. If this code were
|
||||||
|
; to be compiled to C, it would be compiled all the way
|
||||||
|
; to C code with no trace of the original BF code.
|
||||||
(add_grammer_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"]
|
(add_grammer_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"]
|
||||||
(fn* (_ _ _ _ x _ _)
|
(fn* [xs]
|
||||||
`(fn* (input)
|
`(fn* [input]
|
||||||
(let* (
|
(let* (
|
||||||
tape (vector 0 0 0 0 0)
|
arr (atom (vector 0 0 0 0 0))
|
||||||
cursor (make-atom 0)
|
output (atom [])
|
||||||
inptr (make-atom 0)
|
ptr (atom 0)
|
||||||
output (make-atom (vector))
|
inptr (atom 0)
|
||||||
)
|
left (fn* [] (swap! ptr (fn* [old] (- old 1))))
|
||||||
(do (println "beginning bfs") ,x (nth output 0))))))
|
right (fn* [] (swap! ptr (fn* [old] (+ old 1))))
|
||||||
|
plus (fn* [] (swap! arr (fn* [old] (with_update old (deref ptr) (+ (nth (deref arr) (deref ptr)) 1)))))
|
||||||
|
minus (fn* [] (swap! arr (fn* [old] (with_update old (deref ptr) (- (nth (deref arr) (deref ptr)) 1)))))
|
||||||
|
in (fn* [] (let* ( h (nth input (deref inptr))
|
||||||
|
_ (swap! inptr (fn* [old] (+ old 1))))
|
||||||
|
(swap! arr (fn* [old] (with_update old (deref ptr) h)))))
|
||||||
|
out (fn* [] (swap! output (fn* [old] (cons (nth (deref arr) (deref ptr)) old)))))
|
||||||
|
(do ,(nth xs 4) (deref output))))))
|
||||||
|
|
||||||
; Let's try it out! This BF program prints the input 3 times
|
; Let's try it out! This BF program prints the input 3 times
|
||||||
(println (bf { ,>+++[<.>-] } [1337]))
|
(println (bf { ,>+++[<.>-] } [1337]))
|
||||||
; we can also have it compile into our main program (if this wasn't the web version)
|
</textarea>
|
||||||
(def! main (fn* () (do (println "BF: " (bf { ,>+++[<.>-] } [1337])) 0)))
|
<button onclick="executeKraken()">Run</button> <br>
|
||||||
</div>
|
|
||||||
<h4>Output: </h4>
|
<h4>Output: </h4>
|
||||||
<textarea id="bf_output">Output will appear here</textarea>
|
<textarea id="output" cols=130 rows=10>Output will appear here</textarea>
|
||||||
<a name="benchmarks"/>
|
|
||||||
<h3>Performance Benchmarks</h3>
|
|
||||||
<p>Performance is quite poor (for the interpreter mainly, the C compiler seems to be smart enough to make even the very inefficent generated C code fast), as almost no work has gone into it as of yet.
|
|
||||||
We are currently focusing on the FUN-GLL macros and creating a more fully-featured language on top of the core Lisp using them. We will focus more on performance with the implemenation of the functional persistant datastructures and the self-hosting rewrite, and performance will be the main focus of the RVSDG IR part of the project.
|
|
||||||
<p> Even so, it is worth keeping a rough estimate of performance in mind. For this, we have compiled a very basic benchmark below, with more benchmark programs (sorting, etc) to be included as the language gets developed:
|
|
||||||
<br>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th>Core Lisp Interpreter</th>
|
|
||||||
<th>Core Lisp Compiled to C</th>
|
|
||||||
<th>Hand-written C</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td><b>Fibonacci(27)</b></td>
|
|
||||||
<td>51.505s</td>
|
|
||||||
<td>0.007s</td>
|
|
||||||
<td>0.002s</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<br>
|
|
||||||
Here is the core Lisp code run / compiled by the two above tests, which you can run in your web browser. The hand-written C code is an exact translation of this into ideomatic C.
|
|
||||||
<br><i>Note: N is lowered in the web demo so WebAssembly doesn't run out of memory.</i>
|
|
||||||
<a name="fib_example"/>
|
|
||||||
<h4>Fibonacci:</h4>
|
|
||||||
<button onclick="executeKraken(fib_editor.getValue(), 'fib_output')"><b>Run</b></button> <br>
|
|
||||||
<div id="fib_editor">(def! fib (fn* (n) (cond (= 0 n) 0
|
|
||||||
(= 1 n) 1
|
|
||||||
true (+ (fib (- n 1)) (fib (- n 2))))))
|
|
||||||
(let* (n 16)
|
|
||||||
(println "Fib(" n "): " (fib n)))
|
|
||||||
</div>
|
|
||||||
<h4>Output:</h4>
|
|
||||||
<textarea id="fib_output">Output will appear here</textarea>
|
|
||||||
<a name="next_steps"/>
|
|
||||||
<h3>Next Steps</h3>
|
|
||||||
<ul>
|
|
||||||
<li> Implement simple garbage collector for compiled code (currently C)
|
|
||||||
<li> Implement persistant functional data structures
|
|
||||||
<ul>
|
|
||||||
<li> Hash Array-Mapped Trie (HAMT) / Relaxed Radix Balance Tree (RRB-Tree)
|
|
||||||
<li> Hash Map based on the above
|
|
||||||
<li> Hash Set based on the above
|
|
||||||
</ul>
|
|
||||||
<li> Prototype Type Systems as Macros, may require macro system rewrite/upgrade
|
|
||||||
<li> Sketch out Kraken language on top of core Lisp, includes basic Hindley-Milner type system implemented with Macros and above data structures
|
|
||||||
<li> Re-self-host using functional approach in above Kraken language
|
|
||||||
<li> Use Type System Macros to implement automatic transiant creation on HAMT/RBB-Tree as an optimization
|
|
||||||
<li> Implement RVSDG IR and develop best bang-for-buck optimizations using it
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ace.min.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
ace.config.set('basePath', 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/')
|
|
||||||
var hello_editor = ace.edit("hello_editor")
|
|
||||||
var method_editor = ace.edit("method_editor")
|
|
||||||
var bf_editor = ace.edit("bf_editor")
|
|
||||||
var fib_editor = ace.edit("fib_editor")
|
|
||||||
for (let editor of [hello_editor, method_editor, bf_editor, fib_editor]) {
|
|
||||||
editor.session.setMode("ace/mode/clojure")
|
|
||||||
editor.setOption("displayIndentGuides", false)
|
|
||||||
editor.setShowPrintMargin(false)
|
|
||||||
}
|
|
||||||
var output_name = ""
|
|
||||||
var Module = {
|
var Module = {
|
||||||
noInitialRun: true,
|
noInitialRun: true,
|
||||||
onRuntimeInitialized: () => {
|
onRuntimeInitialized: () => {
|
||||||
},
|
},
|
||||||
print: txt => {
|
print: txt => {
|
||||||
document.getElementById(output_name).value += txt + "\n";
|
document.getElementById("output").value += txt + "\n";
|
||||||
},
|
},
|
||||||
printErr: txt => {
|
printErr: txt => {
|
||||||
document.getElementById(output_name).value += "STDERR:[" + txt + "]\n";
|
document.getElementById("output").value += "STDERR:[" + txt + "]\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function executeKraken(code, new_output_name) {
|
function executeKraken() {
|
||||||
output_name = new_output_name
|
document.getElementById("output").value = "";
|
||||||
document.getElementById(new_output_name).value = "running...\n";
|
let code = document.getElementById("code").value;
|
||||||
console.log("gonna execute", code);
|
console.log("gonna execute", code);
|
||||||
Module.callMain(["-C", code]);
|
Module.callMain(["-C", code]);
|
||||||
}
|
}
|
||||||
|
|||||||
112
k_prime.krak
112
k_prime.krak
@@ -230,21 +230,21 @@ obj MalValue (Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun read_str(grammer: ref Grammer<MalResult,MalValue>, s: str): pair<int, MalResult> {
|
fun read_str(grammar: ref Grammer<MalResult,MalValue>, s: str): pair<int, MalResult> {
|
||||||
var BSR = fungll(grammer, grammer.start_symbol, s)
|
var BSR = fungll(grammar, grammar.start_symbol, s)
|
||||||
var longest = -1
|
var longest = -1
|
||||||
for (var i = 0; i < BSR.data.size; i++;) {
|
for (var i = 0; i < BSR.data.size; i++;) {
|
||||||
if BSR.data[i].nonterminal == grammer.start_symbol && BSR.data[i].left == 0 && BSR.data[i].idx_into_rule == grammer.nonterminals[(-1*BSR.data[i].nonterminal)-1][BSR.data[i].rule_idx].size {
|
if BSR.data[i].nonterminal == grammar.start_symbol && BSR.data[i].left == 0 && BSR.data[i].idx_into_rule == grammar.nonterminals[(-1*BSR.data[i].nonterminal)-1][BSR.data[i].rule_idx].size {
|
||||||
longest = BSR.data[i].right
|
longest = BSR.data[i].right
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if longest >= 0 {
|
if longest >= 0 {
|
||||||
return make_pair(longest, grammer.eval_BSR(s.slice(0, longest), BSR))
|
return make_pair(longest, grammar.eval_BSR(s.slice(0, longest), BSR))
|
||||||
} else {
|
} else {
|
||||||
println("trying to parse: " + s)
|
println("trying to parse: " + s)
|
||||||
println(str("length of BSR is: ") + BSR.size())
|
println(str("length of BSR is: ") + BSR.size())
|
||||||
for (var i = 0; i < BSR.data.size; i++;) {
|
for (var i = 0; i < BSR.data.size; i++;) {
|
||||||
println(str() + i + ": " + grammer.to_string(BSR.data[i]))
|
println(str() + i + ": " + grammar.to_string(BSR.data[i]))
|
||||||
}
|
}
|
||||||
println("Parse failed")
|
println("Parse failed")
|
||||||
return make_pair(-1, MalResult::Err(malString(str("failed to parse"))))
|
return make_pair(-1, MalResult::Err(malString(str("failed to parse"))))
|
||||||
@@ -571,8 +571,8 @@ fun pr_str(v: MalValue, print_readably: bool): str {
|
|||||||
error("can't print")
|
error("can't print")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun READ(grammer: ref Grammer<MalResult, MalValue>, s: str): MalResult {
|
fun READ(grammar: ref Grammer<MalResult, MalValue>, s: str): MalResult {
|
||||||
var to_ret = read_str(grammer, s)
|
var to_ret = read_str(grammar, s)
|
||||||
if to_ret.first != s.length() {
|
if to_ret.first != s.length() {
|
||||||
if is_err(to_ret.second) {
|
if is_err(to_ret.second) {
|
||||||
return to_ret.second
|
return to_ret.second
|
||||||
@@ -804,8 +804,8 @@ fun EVAL(env: *Env, ast: MalValue): MalResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rep(grammer: ref Grammer<MalResult, MalValue>, env: *Env, a: str): str {
|
fun rep(grammar: ref Grammer<MalResult, MalValue>, env: *Env, a: str): str {
|
||||||
var read = READ(grammer, a)
|
var read = READ(grammar, a)
|
||||||
if is_err(read) {
|
if is_err(read) {
|
||||||
return pr_str(get_err(read), true)
|
return pr_str(get_err(read), true)
|
||||||
} else {
|
} else {
|
||||||
@@ -830,20 +830,20 @@ fun print_wrapper(params: ref vec<MalValue>, sep: *char, print_readably: bool):
|
|||||||
|
|
||||||
fun main(argc: int, argv: **char): int {
|
fun main(argc: int, argv: **char): int {
|
||||||
|
|
||||||
var grammer.construct(): Grammer<MalResult, MalValue>
|
var grammar.construct(): Grammer<MalResult, MalValue>
|
||||||
|
|
||||||
var ret_nil_term: fun(ref MalValue, ref str, int, int): MalResult = fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(malNil()); }
|
var ret_nil_term: fun(ref MalValue, ref str, int, int): MalResult = fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(malNil()); }
|
||||||
var ret_nil_sym: fun(ref MalValue, ref vec<MalResult>): MalResult = fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return MalResult::Ok(malNil()); }
|
var ret_nil_sym: fun(ref MalValue, ref vec<MalResult>): MalResult = fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return MalResult::Ok(malNil()); }
|
||||||
var ret_0_sym: fun(ref MalValue, ref vec<MalResult>): MalResult = fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return x[0]; }
|
var ret_0_sym: fun(ref MalValue, ref vec<MalResult>): MalResult = fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return x[0]; }
|
||||||
|
|
||||||
var WS = grammer.add_new_nonterminal("WS", vec(grammer.add_terminal("( | |
|
var WS = grammar.add_new_nonterminal("WS", vec(grammar.add_terminal("( | |
|
||||||
|(;[ -~]*
|
|(;[ -~]*
|
||||||
))+", malNil(), ret_nil_term)), malNil(), ret_nil_sym)
|
))+", malNil(), ret_nil_term)), malNil(), ret_nil_sym)
|
||||||
var optional_WS = grammer.add_new_nonterminal("optional_WS", vec<int>(), malNil(), ret_nil_sym)
|
var optional_WS = grammar.add_new_nonterminal("optional_WS", vec<int>(), malNil(), ret_nil_sym)
|
||||||
grammer.add_to_nonterminal(optional_WS, vec(WS), malNil(), ret_nil_sym)
|
grammar.add_to_nonterminal(optional_WS, vec(WS), malNil(), ret_nil_sym)
|
||||||
|
|
||||||
var atom = grammer.add_new_nonterminal("atom", vec(grammer.add_terminal("-?[0-9]+", malNil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(malInt(string_to_num<int>(input.slice(l,r)))); })), malNil(), ret_0_sym)
|
var atom = grammar.add_new_nonterminal("atom", vec(grammar.add_terminal("-?[0-9]+", malNil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(malInt(string_to_num<int>(input.slice(l,r)))); })), malNil(), ret_0_sym)
|
||||||
grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("\"([#-[]| |[]-~]|(\\\\)|(\\n)|(\\t)|(\\\*)|(\\0)|
|
grammar.add_to_nonterminal(atom, vec(grammar.add_terminal("\"([#-[]| |[]-~]|(\\\\)|(\\n)|(\\t)|(\\\*)|(\\0)|
|
||||||
|[ -!]|(\\\\\"))*\"", malNil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { //"
|
|[ -!]|(\\\\\"))*\"", malNil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { //"
|
||||||
var to_ret = str()
|
var to_ret = str()
|
||||||
for (var i = l+1; i < r-1; i++;) {
|
for (var i = l+1; i < r-1; i++;) {
|
||||||
@@ -863,7 +863,7 @@ fun main(argc: int, argv: **char): int {
|
|||||||
}
|
}
|
||||||
return MalResult::Ok(malString(to_ret));
|
return MalResult::Ok(malString(to_ret));
|
||||||
})), malNil(), ret_0_sym)
|
})), malNil(), ret_0_sym)
|
||||||
grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|<|>)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>)*)", malNil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult {
|
grammar.add_to_nonterminal(atom, vec(grammar.add_terminal("-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|<|>)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>)*)", malNil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult {
|
||||||
var s = input.slice(l,r)
|
var s = input.slice(l,r)
|
||||||
if s == "true" {
|
if s == "true" {
|
||||||
return MalResult::Ok(malTrue());
|
return MalResult::Ok(malTrue());
|
||||||
@@ -876,17 +876,17 @@ fun main(argc: int, argv: **char): int {
|
|||||||
}
|
}
|
||||||
})), malNil(), ret_0_sym)
|
})), malNil(), ret_0_sym)
|
||||||
|
|
||||||
var form = grammer.add_new_nonterminal("form", vec(atom), malNil(), ret_0_sym)
|
var form = grammar.add_new_nonterminal("form", vec(atom), malNil(), ret_0_sym)
|
||||||
var space_forms = grammer.add_new_nonterminal("space_forms", vec<int>(), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult {
|
var space_forms = grammar.add_new_nonterminal("space_forms", vec<int>(), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
return MalResult::Ok(malVector(vec<MalValue>()))
|
return MalResult::Ok(malVector(vec<MalValue>()))
|
||||||
})
|
})
|
||||||
grammer.add_to_nonterminal(space_forms, vec(form), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult {
|
grammar.add_to_nonterminal(space_forms, vec(form), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
if is_err(x[0]) {
|
if is_err(x[0]) {
|
||||||
return x[0]
|
return x[0]
|
||||||
}
|
}
|
||||||
return MalResult::Ok(malVector(vec(get_value(x[0]))))
|
return MalResult::Ok(malVector(vec(get_value(x[0]))))
|
||||||
})
|
})
|
||||||
grammer.add_to_nonterminal(space_forms, vec(form, WS, space_forms), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult {
|
grammar.add_to_nonterminal(space_forms, vec(form, WS, space_forms), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
if is_err(x[0]) {
|
if is_err(x[0]) {
|
||||||
return x[0]
|
return x[0]
|
||||||
}
|
}
|
||||||
@@ -896,16 +896,16 @@ fun main(argc: int, argv: **char): int {
|
|||||||
return MalResult::Ok(malVector(vec(get_value(x[0])) + get_value(x[2]).get_vector_rc().get()))
|
return MalResult::Ok(malVector(vec(get_value(x[0])) + get_value(x[2]).get_vector_rc().get()))
|
||||||
})
|
})
|
||||||
|
|
||||||
grammer.add_to_nonterminal(form, vec(grammer.add_terminal("\\(", malNil(), ret_nil_term),
|
grammar.add_to_nonterminal(form, vec(grammar.add_terminal("\\(", malNil(), ret_nil_term),
|
||||||
optional_WS,
|
optional_WS,
|
||||||
grammer.add_terminal("\\)", malNil(), ret_nil_term)), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return MalResult::Ok(malVector(vec<MalValue>())); })
|
grammar.add_terminal("\\)", malNil(), ret_nil_term)), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return MalResult::Ok(malVector(vec<MalValue>())); })
|
||||||
grammer.add_to_nonterminal(form, vec(grammer.add_terminal("\\(", malNil(), ret_nil_term),
|
grammar.add_to_nonterminal(form, vec(grammar.add_terminal("\\(", malNil(), ret_nil_term),
|
||||||
optional_WS,
|
optional_WS,
|
||||||
space_forms,
|
space_forms,
|
||||||
optional_WS,
|
optional_WS,
|
||||||
grammer.add_terminal("\\)", malNil(), ret_nil_term)), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return x[2]; })
|
grammar.add_terminal("\\)", malNil(), ret_nil_term)), malNil(), fun(_: ref MalValue, x: ref vec<MalResult>): MalResult { return x[2]; })
|
||||||
|
|
||||||
grammer.set_start_symbol(form)
|
grammar.set_start_symbol(form)
|
||||||
|
|
||||||
|
|
||||||
var env = new<Env>()->construct()
|
var env = new<Env>()->construct()
|
||||||
@@ -1043,7 +1043,7 @@ fun main(argc: int, argv: **char): int {
|
|||||||
if params.size != 1 || !params[0].is_string() {
|
if params.size != 1 || !params[0].is_string() {
|
||||||
return MalResult::Err(malString(str("read-string with not a single string")))
|
return MalResult::Err(malString(str("read-string with not a single string")))
|
||||||
} else {
|
} else {
|
||||||
return READ(grammer, params[0].get_string())
|
return READ(grammar, params[0].get_string())
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
env->set(str("slurp"), make_builtin_function(str("slurp"), fun(params: vec<MalValue>): MalResult {
|
env->set(str("slurp"), make_builtin_function(str("slurp"), fun(params: vec<MalValue>): MalResult {
|
||||||
@@ -1227,19 +1227,19 @@ fun main(argc: int, argv: **char): int {
|
|||||||
env->set(str("string?"), make_builtin_function(str("string?"), fun(params: vec<MalValue>): MalResult {
|
env->set(str("string?"), make_builtin_function(str("string?"), fun(params: vec<MalValue>): MalResult {
|
||||||
return MalResult::Err(malString(str("not implemented")))
|
return MalResult::Err(malString(str("not implemented")))
|
||||||
}));
|
}));
|
||||||
// self-modifying grammer
|
// self-modifying grammar
|
||||||
env->set(str("add_terminal"), make_builtin_function(str("add_terminal"), fun(params: vec<MalValue>): MalResult {
|
env->set(str("add_terminal"), make_builtin_function(str("add_terminal"), fun(params: vec<MalValue>): MalResult {
|
||||||
if params.size != 2 || !params[0].is_string() {
|
if params.size != 2 || !params[0].is_string() {
|
||||||
return MalResult::Err(malString(str("add_terminal called with wrong number or type of params")))
|
return MalResult::Err(malString(str("add_terminal called with wrong number or type of params")))
|
||||||
} else {
|
} else {
|
||||||
return MalResult::Ok(malInt(grammer.add_terminal(params[0].get_string(), params[1], fun(f: ref MalValue, input: ref str, l: int, r: int): MalResult {
|
return MalResult::Ok(malInt(grammar.add_terminal(params[0].get_string(), params[1], fun(f: ref MalValue, input: ref str, l: int, r: int): MalResult {
|
||||||
return function_call(f, vec(malString(input.slice(l,r))))
|
return function_call(f, vec(malString(input.slice(l,r))))
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
env->set(str("add_grammer_rule"), make_builtin_function(str("add_grammer_rule"), fun(params: vec<MalValue>): MalResult {
|
env->set(str("add_grammar_rule"), make_builtin_function(str("add_grammar_rule"), fun(params: vec<MalValue>): MalResult {
|
||||||
if params.size != 3 || !params[0].is_symbol() || !params[1].is_vector() {
|
if params.size != 3 || !params[0].is_symbol() || !params[1].is_vector() {
|
||||||
return MalResult::Err(malString(str("add_grammer_rule called with wrong number or type of params")))
|
return MalResult::Err(malString(str("add_grammar_rule called with wrong number or type of params")))
|
||||||
} else {
|
} else {
|
||||||
var nonterminal_str = params[0].get_symbol_text()
|
var nonterminal_str = params[0].get_symbol_text()
|
||||||
var rule = params[1].get_vector_rc().get()
|
var rule = params[1].get_vector_rc().get()
|
||||||
@@ -1248,14 +1248,14 @@ fun main(argc: int, argv: **char): int {
|
|||||||
if rule[i].is_int() {
|
if rule[i].is_int() {
|
||||||
int_rule.add(rule[i].get_int())
|
int_rule.add(rule[i].get_int())
|
||||||
} else if rule[i].is_symbol() {
|
} else if rule[i].is_symbol() {
|
||||||
var sub_nonterminal_idx = grammer.nonterminal_names.find(rule[i].get_symbol_text())
|
var sub_nonterminal_idx = grammar.nonterminal_names.find(rule[i].get_symbol_text())
|
||||||
if sub_nonterminal_idx == -1 {
|
if sub_nonterminal_idx == -1 {
|
||||||
return MalResult::Err(malString(str("Couldn't find nonterminal: ") + rule[i].get_symbol_text()))
|
return MalResult::Err(malString(str("Couldn't find nonterminal: ") + rule[i].get_symbol_text()))
|
||||||
}
|
}
|
||||||
var sub_nonterminal = -1*(sub_nonterminal_idx+1)
|
var sub_nonterminal = -1*(sub_nonterminal_idx+1)
|
||||||
int_rule.add(sub_nonterminal)
|
int_rule.add(sub_nonterminal)
|
||||||
} else if rule[i].is_string() {
|
} else if rule[i].is_string() {
|
||||||
int_rule.add(grammer.add_terminal(rule[i].get_string(), malNil(), fun(f: ref MalValue, input: ref str, l: int, r: int): MalResult {
|
int_rule.add(grammar.add_terminal(rule[i].get_string(), malNil(), fun(f: ref MalValue, input: ref str, l: int, r: int): MalResult {
|
||||||
return MalResult::Ok(malString(input.slice(l,r)))
|
return MalResult::Ok(malString(input.slice(l,r)))
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
@@ -1263,25 +1263,25 @@ fun main(argc: int, argv: **char): int {
|
|||||||
MalValue_int::BuiltinFunction(f) {
|
MalValue_int::BuiltinFunction(f) {
|
||||||
if f.name == "+" || f.name == "*" {
|
if f.name == "+" || f.name == "*" {
|
||||||
if int_rule.size == 0 {
|
if int_rule.size == 0 {
|
||||||
return MalResult::Err(malString(str("add_grammer_rule has + or * in first position, with nothing to repeat")))
|
return MalResult::Err(malString(str("add_grammar_rule has + or * in first position, with nothing to repeat")))
|
||||||
}
|
}
|
||||||
var current = int_rule.last()
|
var current = int_rule.last()
|
||||||
var sub_rule_names = nonterminal_str + "_" + new_tmp()
|
var sub_rule_names = nonterminal_str + "_" + new_tmp()
|
||||||
var new = grammer.add_to_or_create_nonterminal(sub_rule_names + "_one_or_more", vec(current), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
var new = grammar.add_to_or_create_nonterminal(sub_rule_names + "_one_or_more", vec(current), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
if is_err(x[0]) { return x[0]; }
|
if is_err(x[0]) { return x[0]; }
|
||||||
return MalResult::Ok(malVector(vec(get_value(x[0]))))
|
return MalResult::Ok(malVector(vec(get_value(x[0]))))
|
||||||
})
|
})
|
||||||
grammer.add_to_nonterminal(new, vec(current, new), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
grammar.add_to_nonterminal(new, vec(current, new), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
if is_err(x[0]) { return x[0]; }
|
if is_err(x[0]) { return x[0]; }
|
||||||
if is_err(x[1]) { return x[1]; }
|
if is_err(x[1]) { return x[1]; }
|
||||||
return MalResult::Ok(malVector(vec(get_value(x[0])) + get_value(x[1]).get_vector_rc().get()))
|
return MalResult::Ok(malVector(vec(get_value(x[0])) + get_value(x[1]).get_vector_rc().get()))
|
||||||
})
|
})
|
||||||
if f.name == "*" {
|
if f.name == "*" {
|
||||||
new = grammer.add_to_or_create_nonterminal(sub_rule_names + "_zero_or_more", vec(new), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
new = grammar.add_to_or_create_nonterminal(sub_rule_names + "_zero_or_more", vec(new), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
if is_err(x[0]) { return x[0]; }
|
if is_err(x[0]) { return x[0]; }
|
||||||
return MalResult::Ok(get_value(x[0]))
|
return MalResult::Ok(get_value(x[0]))
|
||||||
})
|
})
|
||||||
grammer.add_to_nonterminal(new, vec<int>(), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
grammar.add_to_nonterminal(new, vec<int>(), malNil(), fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
return MalResult::Ok(malVector(vec<MalValue>()))
|
return MalResult::Ok(malVector(vec<MalValue>()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1290,10 +1290,10 @@ fun main(argc: int, argv: **char): int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MalResult::Err(malString(str("add_grammer_rule called with not symbol, int, or string in rule")))
|
return MalResult::Err(malString(str("add_grammar_rule called with not symbol, int, or string in rule")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grammer.add_to_or_create_nonterminal(nonterminal_str, int_rule, params[2], fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
grammar.add_to_or_create_nonterminal(nonterminal_str, int_rule, params[2], fun(f: ref MalValue, x: ref vec<MalResult>): MalResult {
|
||||||
var params = vec<MalValue>()
|
var params = vec<MalValue>()
|
||||||
for (var i = 0; i < x.size; i++;) {
|
for (var i = 0; i < x.size; i++;) {
|
||||||
if is_err(x[i]) {
|
if is_err(x[i]) {
|
||||||
@@ -1315,7 +1315,7 @@ fun main(argc: int, argv: **char): int {
|
|||||||
var current_ret = MalResult::Ok(malNil())
|
var current_ret = MalResult::Ok(malNil())
|
||||||
if i < input.length() {
|
if i < input.length() {
|
||||||
// initial handle whitespace
|
// initial handle whitespace
|
||||||
var BSR = fungll(grammer, optional_WS, input.slice(i, -1))
|
var BSR = fungll(grammar, optional_WS, input.slice(i, -1))
|
||||||
var longest = -1
|
var longest = -1
|
||||||
for (var j = 0; j < BSR.data.size; j++;) {
|
for (var j = 0; j < BSR.data.size; j++;) {
|
||||||
if BSR.data[j].nonterminal == optional_WS && BSR.data[j].left == 0 {
|
if BSR.data[j].nonterminal == optional_WS && BSR.data[j].left == 0 {
|
||||||
@@ -1329,7 +1329,7 @@ fun main(argc: int, argv: **char): int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while i < input.length() {
|
while i < input.length() {
|
||||||
var r = read_str(grammer, input.slice(i, -1))
|
var r = read_str(grammar, input.slice(i, -1))
|
||||||
i += r.first
|
i += r.first
|
||||||
if is_err(r.second) {
|
if is_err(r.second) {
|
||||||
return r.second
|
return r.second
|
||||||
@@ -1339,7 +1339,7 @@ fun main(argc: int, argv: **char): int {
|
|||||||
return current_ret
|
return current_ret
|
||||||
}
|
}
|
||||||
// handle whitespace again
|
// handle whitespace again
|
||||||
var BSR = fungll(grammer, optional_WS, input.slice(i, -1))
|
var BSR = fungll(grammar, optional_WS, input.slice(i, -1))
|
||||||
var longest = -1
|
var longest = -1
|
||||||
for (var j = 0; j < BSR.data.size; j++;) {
|
for (var j = 0; j < BSR.data.size; j++;) {
|
||||||
if BSR.data[j].nonterminal == optional_WS && BSR.data[j].left == 0 {
|
if BSR.data[j].nonterminal == optional_WS && BSR.data[j].left == 0 {
|
||||||
@@ -1357,21 +1357,21 @@ fun main(argc: int, argv: **char): int {
|
|||||||
}
|
}
|
||||||
env->set(str("eval-read-string"), make_builtin_function(str("eval-read-string"), ERS));
|
env->set(str("eval-read-string"), make_builtin_function(str("eval-read-string"), ERS));
|
||||||
// reader macros
|
// reader macros
|
||||||
rep(grammer, env, str("(add_grammer_rule (quote atom) (vector \"'\" (quote form)) (fn* (_ x) (quasiquote (quote (unquote x)))))")) //'
|
rep(grammar, env, str("(add_grammar_rule (quote atom) (vector \"'\" (quote form)) (fn* (_ x) (quasiquote (quote (unquote x)))))")) //'
|
||||||
rep(grammer, env, str("(add_grammer_rule 'form (vector \"\\\\[\" 'optional_WS \"\\\\]\") (fn* (& _) '(vector)))")) //'
|
rep(grammar, env, str("(add_grammar_rule 'form (vector \"\\\\[\" 'optional_WS \"\\\\]\") (fn* (& _) '(vector)))")) //'
|
||||||
rep(grammer, env, str("(add_grammer_rule 'form (vector \"\\\\[\" 'optional_WS 'space_forms 'optional_WS \"\\\\]\") (fn* (_ _ x _ _) (quasiquote (vector (splice-unquote x)))))")) //'
|
rep(grammar, env, str("(add_grammar_rule 'form (vector \"\\\\[\" 'optional_WS 'space_forms 'optional_WS \"\\\\]\") (fn* (_ _ x _ _) (quasiquote (vector (splice-unquote x)))))")) //'
|
||||||
// now we can use ' for the rest
|
// now we can use ' for the rest
|
||||||
rep(grammer, env, str("(add_grammer_rule 'atom [\"`\" 'form] (fn* (_ x) (quasiquote (quasiquote (unquote x)))))"))
|
rep(grammar, env, str("(add_grammar_rule 'atom [\"`\" 'form] (fn* (_ x) (quasiquote (quasiquote (unquote x)))))"))
|
||||||
rep(grammer, env, str("(add_grammer_rule 'atom [\"~\" 'form] (fn* (_ x) (vector (quote unquote) x)))"))
|
rep(grammar, env, str("(add_grammar_rule 'atom [\"~\" 'form] (fn* (_ x) (vector (quote unquote) x)))"))
|
||||||
// the standard appears to be for splice-unquote to be <symbol-for-unqoute><symbol-for-deref>, but unquote deref is a reasonable
|
// the standard appears to be for splice-unquote to be <symbol-for-unqoute><symbol-for-deref>, but unquote deref is a reasonable
|
||||||
// sequence of characters and causes ambigious parses! So I chose the other common unquote symbol to be splice-unquote
|
// sequence of characters and causes ambigious parses! So I chose the other common unquote symbol to be splice-unquote
|
||||||
rep(grammer, env, str("(add_grammer_rule 'atom [\",\" 'form] (fn* (_ x) (vector (quote splice-unquote) x)))"))
|
rep(grammar, env, str("(add_grammar_rule 'atom [\",\" 'form] (fn* (_ x) (vector (quote splice-unquote) x)))"))
|
||||||
rep(grammer, env, str("(add_grammer_rule 'atom [\"@\" 'form] (fn* (_ x) `(deref ~x)))")) //"
|
rep(grammar, env, str("(add_grammar_rule 'atom [\"@\" 'form] (fn* (_ x) `(deref ~x)))")) //"
|
||||||
|
|
||||||
rep(grammer, env, str("(def! not (fn* (a) (if a false true)))"))
|
rep(grammar, env, str("(def! not (fn* (a) (if a false true)))"))
|
||||||
rep(grammer, env, str("(def! load-file (fn* (f) (eval-read-string (slurp f))))"))
|
rep(grammar, env, str("(def! load-file (fn* (f) (eval-read-string (slurp f))))"))
|
||||||
rep(grammer, env, str("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (vector 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"))
|
rep(grammar, env, str("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (vector 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"))
|
||||||
rep(grammer, env, str("(def! nil? (fn* (a) (= nil a)))"))
|
rep(grammar, env, str("(def! nil? (fn* (a) (= nil a)))"))
|
||||||
var params = vec<MalValue>()
|
var params = vec<MalValue>()
|
||||||
if argc == 3 && str(argv[1]) == "-C" {
|
if argc == 3 && str(argv[1]) == "-C" {
|
||||||
env->set(str("*ARGV*"), malNil())
|
env->set(str("*ARGV*"), malNil())
|
||||||
@@ -1386,7 +1386,7 @@ fun main(argc: int, argv: **char): int {
|
|||||||
params.add(malString(str(argv[i])))
|
params.add(malString(str(argv[i])))
|
||||||
}
|
}
|
||||||
env->set(str("*ARGV*"), malVector(params))
|
env->set(str("*ARGV*"), malVector(params))
|
||||||
var eval_result_str = rep(grammer, env, str("(load-file \"") + argv[1] + "\")")
|
var eval_result_str = rep(grammar, env, str("(load-file \"") + argv[1] + "\")")
|
||||||
println(eval_result_str)
|
println(eval_result_str)
|
||||||
if eval_result_str.length() >= 11 && eval_result_str.slice(0,11) == "Exception: " {
|
if eval_result_str.length() >= 11 && eval_result_str.slice(0,11) == "Exception: " {
|
||||||
error("aborting compile")
|
error("aborting compile")
|
||||||
@@ -1662,12 +1662,12 @@ fun main(argc: int, argv: **char): int {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
env->set(str("*ARGV*"), malVector(params))
|
env->set(str("*ARGV*"), malVector(params))
|
||||||
rep(grammer, env, str("(println (str \"Mal [\" *host-language* \"]\"))"))
|
rep(grammar, env, str("(println (str \"Mal [\" *host-language* \"]\"))"))
|
||||||
while (true) {
|
while (true) {
|
||||||
var line = get_line(str("user> "), 1024)
|
var line = get_line(str("user> "), 1024)
|
||||||
if (line == "***EOF***")
|
if (line == "***EOF***")
|
||||||
break
|
break
|
||||||
println(rep(grammer, env, line))
|
println(rep(grammar, env, line))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
(println "no method " method)
|
(println "no method " method)
|
||||||
(apply method_fn object arguments)))))
|
(apply method_fn object arguments)))))
|
||||||
; method call syntax
|
; method call syntax
|
||||||
(add_grammer_rule 'form [ 'form "\\." 'atom 'optional_WS "\\(" 'optional_WS 'space_forms 'optional_WS "\\)" ] (fn* (o _ m _ _ _ p _ _) `(method-call ~o '~m ,p)))
|
(add_grammar_rule 'form [ 'form "\\." 'atom 'optional_WS "\\(" 'optional_WS 'space_forms 'optional_WS "\\)" ] (fn* (o _ m _ _ _ p _ _) `(method-call ~o '~m ,p)))
|
||||||
(def! actual_obj (with-meta [0] [
|
(def! actual_obj (with-meta [0] [
|
||||||
'inc (fn* (o) (set-nth! o 0 (+ (nth o 0) 1)))
|
'inc (fn* (o) (set-nth! o 0 (+ (nth o 0) 1)))
|
||||||
'dec (fn* (o) (set-nth! o 0 (- (nth o 0) 1)))
|
'dec (fn* (o) (set-nth! o 0 (- (nth o 0) 1)))
|
||||||
|
|||||||
Reference in New Issue
Block a user