2016-07-25 06:38:31 +00:00
|
|
|
## experimental compiler to translate programs written in a generic
|
2016-10-22 23:56:07 +00:00
|
|
|
## expression-oriented language called 'lambda' into Mu
|
2016-07-23 20:54:45 +00:00
|
|
|
|
2016-11-25 19:33:13 +00:00
|
|
|
# incomplete; code generator not done
|
|
|
|
# potential enhancements:
|
|
|
|
# symbol table
|
|
|
|
# poor man's macros
|
2017-12-04 07:25:40 +00:00
|
|
|
# substitute one instruction with multiple, parameterized by inputs and products
|
2016-11-25 19:33:13 +00:00
|
|
|
|
2016-07-23 20:54:45 +00:00
|
|
|
scenario convert-lambda [
|
2016-07-22 18:04:42 +00:00
|
|
|
run [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
1:text/raw <- lambda-to-mu [(add a (multiply b c))]
|
2016-09-17 20:00:39 +00:00
|
|
|
2:@:char/raw <- copy *1:text/raw
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-11-22 19:14:43 +00:00
|
|
|
2:array:character <- [t1 <- multiply b c
|
2016-07-22 18:04:42 +00:00
|
|
|
result <- add a t1]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2016-09-17 07:10:28 +00:00
|
|
|
def lambda-to-mu in:text -> out:text [
|
2016-07-22 21:00:12 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2018-06-17 18:20:53 +00:00
|
|
|
out <- copy null
|
2016-09-17 19:55:10 +00:00
|
|
|
cells:&:cell <- parse in
|
2016-07-24 22:04:41 +00:00
|
|
|
out <- to-mu cells
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
|
2016-07-23 20:54:45 +00:00
|
|
|
# 'parse' will turn lambda expressions into trees made of cells
|
2016-07-22 21:00:12 +00:00
|
|
|
exclusive-container cell [
|
2016-09-12 07:47:44 +00:00
|
|
|
atom:text
|
2016-07-22 21:00:12 +00:00
|
|
|
pair:pair
|
|
|
|
]
|
|
|
|
|
2016-07-23 20:54:39 +00:00
|
|
|
# printed below as < first | rest >
|
2016-07-22 21:00:12 +00:00
|
|
|
container pair [
|
2016-09-17 19:55:10 +00:00
|
|
|
first:&:cell
|
|
|
|
rest:&:cell
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def new-atom name:text -> result:&:cell [
|
2016-07-22 18:04:42 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-07-22 18:04:42 +00:00
|
|
|
result <- new cell:type
|
2016-07-22 21:00:12 +00:00
|
|
|
*result <- merge 0/tag:atom, name
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def new-pair a:&:cell, b:&:cell -> result:&:cell [
|
2016-07-22 18:04:42 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-07-22 18:04:42 +00:00
|
|
|
result <- new cell:type
|
2016-07-22 21:00:12 +00:00
|
|
|
*result <- merge 1/tag:pair, a/first, b/rest
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
|
2016-10-08 17:52:58 +00:00
|
|
|
def is-atom? x:&:cell -> result:bool [
|
2016-07-22 21:00:12 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2018-06-17 07:05:38 +00:00
|
|
|
return-unless x, false
|
2016-07-22 21:00:12 +00:00
|
|
|
_, result <- maybe-convert *x, atom:variant
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
|
2016-10-08 17:52:58 +00:00
|
|
|
def is-pair? x:&:cell -> result:bool [
|
2016-07-22 21:00:12 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2018-06-17 07:05:38 +00:00
|
|
|
return-unless x, false
|
2016-07-22 21:00:12 +00:00
|
|
|
_, result <- maybe-convert *x, pair:variant
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
|
|
|
|
2016-07-22 21:07:53 +00:00
|
|
|
scenario atom-is-not-pair [
|
2016-07-22 18:04:42 +00:00
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [a]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- new-atom s
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-atom? x
|
|
|
|
11:bool/raw <- is-pair? x
|
2016-07-22 21:00:12 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1
|
2016-07-22 21:07:53 +00:00
|
|
|
11 <- 0
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
scenario pair-is-not-atom [
|
|
|
|
local-scope
|
|
|
|
# construct (a . nil)
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [a]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- new-atom s
|
2018-06-17 18:20:53 +00:00
|
|
|
y:&:cell <- new-pair x, null
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-atom? y
|
|
|
|
11:bool/raw <- is-pair? y
|
2016-07-22 21:07:53 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 0
|
|
|
|
11 <- 1
|
2016-07-22 21:00:12 +00:00
|
|
|
]
|
2016-07-22 18:04:42 +00:00
|
|
|
]
|
2016-07-22 21:15:24 +00:00
|
|
|
|
2016-10-08 17:52:58 +00:00
|
|
|
def atom-match? x:&:cell, pat:text -> result:bool [
|
2016-07-24 22:58:26 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-10-08 17:52:58 +00:00
|
|
|
s:text, is-atom?:bool <- maybe-convert *x, atom:variant
|
2018-06-17 07:05:38 +00:00
|
|
|
return-unless is-atom?, false
|
2016-07-24 22:58:26 +00:00
|
|
|
result <- equal pat, s
|
|
|
|
]
|
|
|
|
|
|
|
|
scenario atom-match [
|
|
|
|
local-scope
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- new-atom [abc]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- atom-match? x, [abc]
|
2016-07-24 22:58:26 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def first x:&:cell -> result:&:cell [
|
2016-07-22 21:15:24 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-10-08 17:52:58 +00:00
|
|
|
pair:pair, pair?:bool <- maybe-convert *x, pair:variant
|
2018-06-17 18:20:53 +00:00
|
|
|
return-unless pair?, null
|
2016-07-22 21:15:24 +00:00
|
|
|
result <- get pair, first:offset
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def rest x:&:cell -> result:&:cell [
|
2016-07-22 21:15:24 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-10-08 17:52:58 +00:00
|
|
|
pair:pair, pair?:bool <- maybe-convert *x, pair:variant
|
2018-06-17 18:20:53 +00:00
|
|
|
return-unless pair?, null
|
2016-07-22 21:15:24 +00:00
|
|
|
result <- get pair, rest:offset
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def set-first base:&:cell, new-first:&:cell -> base:&:cell [
|
2016-07-24 22:58:15 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-10-08 17:52:58 +00:00
|
|
|
pair:pair, is-pair?:bool <- maybe-convert *base, pair:variant
|
2016-11-10 18:24:14 +00:00
|
|
|
return-unless is-pair?
|
2016-07-24 22:58:15 +00:00
|
|
|
pair <- put pair, first:offset, new-first
|
|
|
|
*base <- merge 1/pair, pair
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def set-rest base:&:cell, new-rest:&:cell -> base:&:cell [
|
2016-07-24 22:58:15 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-10-08 17:52:58 +00:00
|
|
|
pair:pair, is-pair?:bool <- maybe-convert *base, pair:variant
|
2016-11-10 18:24:14 +00:00
|
|
|
return-unless is-pair?
|
2016-07-24 22:58:15 +00:00
|
|
|
pair <- put pair, rest:offset, new-rest
|
|
|
|
*base <- merge 1/pair, pair
|
|
|
|
]
|
|
|
|
|
2016-07-22 21:15:24 +00:00
|
|
|
scenario cell-operations-on-atom [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [a]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- new-atom s
|
|
|
|
10:&:cell/raw <- first x
|
|
|
|
11:&:cell/raw <- rest x
|
2016-07-22 21:15:24 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 0 # first is nil
|
|
|
|
11 <- 0 # rest is nil
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
scenario cell-operations-on-pair [
|
|
|
|
local-scope
|
|
|
|
# construct (a . nil)
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [a]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- new-atom s
|
2018-06-17 18:20:53 +00:00
|
|
|
y:&:cell <- new-pair x, null
|
2016-09-17 19:55:10 +00:00
|
|
|
x2:&:cell <- first y
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- equal x, x2
|
2016-09-17 19:55:10 +00:00
|
|
|
11:&:cell/raw <- rest y
|
2016-07-22 21:15:24 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # first is correct
|
|
|
|
11 <- 0 # rest is nil
|
|
|
|
]
|
|
|
|
]
|
2016-07-23 02:56:18 +00:00
|
|
|
|
2016-07-25 06:38:31 +00:00
|
|
|
## convert lambda text to a tree of cells
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def parse in:text -> out:&:cell [
|
2016-07-23 02:56:18 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-09-17 19:55:10 +00:00
|
|
|
s:&:stream:char <- new-stream in
|
2016-07-23 02:56:18 +00:00
|
|
|
out, s <- parse s
|
2016-07-24 22:04:41 +00:00
|
|
|
trace 2, [app/parse], out
|
2016-07-23 02:56:18 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def parse in:&:stream:char -> out:&:cell, in:&:stream:char [
|
2016-07-23 02:56:18 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-07-24 22:25:56 +00:00
|
|
|
# skip whitespace
|
|
|
|
in <- skip-whitespace in
|
2016-10-08 17:52:58 +00:00
|
|
|
c:char, eof?:bool <- peek in
|
2018-06-17 18:20:53 +00:00
|
|
|
return-if eof?, null
|
2016-10-08 17:52:58 +00:00
|
|
|
pair?:bool <- equal c, 40/open-paren
|
2016-07-23 02:58:30 +00:00
|
|
|
{
|
2016-07-23 03:34:29 +00:00
|
|
|
break-if pair?
|
|
|
|
# atom
|
2017-04-18 22:44:31 +00:00
|
|
|
buf:&:buffer:char <- new-buffer 30
|
2016-07-23 03:28:51 +00:00
|
|
|
{
|
2016-10-08 17:52:58 +00:00
|
|
|
done?:bool <- end-of-stream? in
|
2016-07-23 03:34:29 +00:00
|
|
|
break-if done?
|
2016-07-24 22:25:56 +00:00
|
|
|
# stop before close paren or space
|
2016-09-17 07:31:55 +00:00
|
|
|
c:char <- peek in
|
2016-07-23 04:16:09 +00:00
|
|
|
done? <- equal c, 41/close-paren
|
|
|
|
break-if done?
|
2016-07-24 22:25:56 +00:00
|
|
|
done? <- space? c
|
2016-07-23 04:16:09 +00:00
|
|
|
break-if done?
|
2016-07-24 22:25:56 +00:00
|
|
|
c <- read in
|
2016-10-20 22:04:01 +00:00
|
|
|
buf <- append buf, c
|
2016-07-23 03:34:29 +00:00
|
|
|
loop
|
2016-07-23 03:28:51 +00:00
|
|
|
}
|
2016-10-20 22:04:01 +00:00
|
|
|
s:text <- buffer-to-array buf
|
2016-07-23 03:34:29 +00:00
|
|
|
out <- new-atom s
|
|
|
|
}
|
|
|
|
{
|
|
|
|
break-unless pair?
|
|
|
|
# pair
|
|
|
|
read in # skip the open-paren
|
2016-07-23 20:54:39 +00:00
|
|
|
out <- new cell:type # start out with nil
|
|
|
|
# read in first element of pair
|
|
|
|
{
|
2016-10-08 17:52:58 +00:00
|
|
|
end?:bool <- end-of-stream? in
|
|
|
|
not-end?:bool <- not end?
|
2016-07-23 21:17:35 +00:00
|
|
|
assert not-end?, [unbalanced '(' in expression]
|
2016-07-23 20:54:39 +00:00
|
|
|
c <- peek in
|
2016-10-08 17:52:58 +00:00
|
|
|
close-paren?:bool <- equal c, 41/close-paren
|
2016-07-23 20:54:39 +00:00
|
|
|
break-if close-paren?
|
2016-09-17 19:55:10 +00:00
|
|
|
first:&:cell, in <- parse in
|
2018-06-17 18:20:53 +00:00
|
|
|
*out <- merge 1/pair, first, null
|
2016-07-23 20:54:39 +00:00
|
|
|
}
|
|
|
|
# read in any remaining elements
|
2016-09-17 19:55:10 +00:00
|
|
|
curr:&:cell <- copy out
|
2016-07-23 20:54:39 +00:00
|
|
|
{
|
2016-07-28 05:33:18 +00:00
|
|
|
in <- skip-whitespace in
|
2016-10-08 17:52:58 +00:00
|
|
|
end?:bool <- end-of-stream? in
|
|
|
|
not-end?:bool <- not end?
|
2016-07-23 21:17:35 +00:00
|
|
|
assert not-end?, [unbalanced '(' in expression]
|
2016-07-24 23:09:18 +00:00
|
|
|
# termination check: ')'
|
2016-07-23 20:54:39 +00:00
|
|
|
c <- peek in
|
2016-07-24 22:46:59 +00:00
|
|
|
{
|
2016-10-08 17:52:58 +00:00
|
|
|
close-paren?:bool <- equal c, 41/close-paren
|
2016-07-24 22:46:59 +00:00
|
|
|
break-unless close-paren?
|
|
|
|
read in # skip ')'
|
2016-10-22 19:08:10 +00:00
|
|
|
break +end-pair
|
2016-07-24 22:46:59 +00:00
|
|
|
}
|
2016-07-24 23:09:18 +00:00
|
|
|
# still here? read next element of pair
|
2016-09-17 19:55:10 +00:00
|
|
|
next:&:cell, in <- parse in
|
2016-10-08 17:52:58 +00:00
|
|
|
is-dot?:bool <- atom-match? next, [.]
|
2016-07-24 23:09:18 +00:00
|
|
|
{
|
|
|
|
break-if is-dot?
|
2018-06-17 18:20:53 +00:00
|
|
|
next-curr:&:cell <- new-pair next, null
|
2016-07-24 23:09:18 +00:00
|
|
|
curr <- set-rest curr, next-curr
|
|
|
|
curr <- rest curr
|
|
|
|
}
|
|
|
|
{
|
|
|
|
break-unless is-dot?
|
|
|
|
# deal with dotted pair
|
|
|
|
in <- skip-whitespace in
|
|
|
|
c <- peek in
|
2016-10-08 17:52:58 +00:00
|
|
|
not-close-paren?:bool <- not-equal c, 41/close-paren
|
2016-07-24 23:09:18 +00:00
|
|
|
assert not-close-paren?, [')' cannot immediately follow '.']
|
2016-09-17 19:55:10 +00:00
|
|
|
final:&:cell <- parse in
|
2016-07-24 23:09:18 +00:00
|
|
|
curr <- set-rest curr, final
|
2016-07-24 23:16:48 +00:00
|
|
|
# we're not gonna update curr, so better make sure the next iteration
|
|
|
|
# is going to end the pair
|
2016-07-24 23:09:18 +00:00
|
|
|
in <- skip-whitespace in
|
|
|
|
c <- peek in
|
2016-10-08 17:52:58 +00:00
|
|
|
close-paren?:bool <- equal c, 41/close-paren
|
2016-07-24 23:16:48 +00:00
|
|
|
assert close-paren?, ['.' must be followed by exactly one expression before ')']
|
2016-07-24 23:09:18 +00:00
|
|
|
}
|
2016-07-23 20:54:39 +00:00
|
|
|
loop
|
|
|
|
}
|
2016-07-24 22:46:59 +00:00
|
|
|
+end-pair
|
2016-07-23 02:58:30 +00:00
|
|
|
}
|
2016-07-23 02:56:18 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def skip-whitespace in:&:stream:char -> in:&:stream:char [
|
2016-07-24 22:25:56 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-07-24 22:25:56 +00:00
|
|
|
{
|
2016-10-08 17:52:58 +00:00
|
|
|
done?:bool <- end-of-stream? in
|
2018-06-17 18:20:53 +00:00
|
|
|
return-if done?, null
|
2016-09-17 07:31:55 +00:00
|
|
|
c:char <- peek in
|
2016-10-08 17:52:58 +00:00
|
|
|
space?:bool <- space? c
|
2016-07-24 22:25:56 +00:00
|
|
|
break-unless space?
|
|
|
|
read in # skip
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def to-text x:&:cell -> out:text [
|
2016-07-24 22:04:41 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2017-04-18 22:44:31 +00:00
|
|
|
buf:&:buffer:char <- new-buffer 30
|
2016-07-24 22:04:41 +00:00
|
|
|
buf <- to-buffer x, buf
|
|
|
|
out <- buffer-to-array buf
|
|
|
|
]
|
|
|
|
|
2017-04-18 22:44:31 +00:00
|
|
|
def to-buffer x:&:cell, buf:&:buffer:char -> buf:&:buffer:char [
|
2016-07-24 22:04:41 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-07-24 22:04:41 +00:00
|
|
|
# base case: empty cell
|
|
|
|
{
|
|
|
|
break-if x
|
|
|
|
buf <- append buf, [<>]
|
2016-11-10 18:24:14 +00:00
|
|
|
return
|
2016-07-24 22:04:41 +00:00
|
|
|
}
|
|
|
|
# base case: atom
|
|
|
|
{
|
2016-10-08 17:52:58 +00:00
|
|
|
s:text, atom?:bool <- maybe-convert *x, atom:variant
|
2016-07-24 22:04:41 +00:00
|
|
|
break-unless atom?
|
|
|
|
buf <- append buf, s
|
2016-11-10 18:24:14 +00:00
|
|
|
return
|
2016-07-24 22:04:41 +00:00
|
|
|
}
|
|
|
|
# recursive case: pair
|
|
|
|
buf <- append buf, [< ]
|
2016-09-17 19:55:10 +00:00
|
|
|
first:&:cell <- first x
|
2016-07-24 22:04:41 +00:00
|
|
|
buf <- to-buffer first, buf
|
|
|
|
buf <- append buf, [ | ]
|
2016-09-17 19:55:10 +00:00
|
|
|
rest:&:cell <- rest x
|
2016-07-24 22:04:41 +00:00
|
|
|
buf <- to-buffer rest, buf
|
|
|
|
buf <- append buf, [ >]
|
|
|
|
]
|
|
|
|
|
2016-07-23 02:58:30 +00:00
|
|
|
scenario parse-single-letter-atom [
|
2016-07-23 02:56:18 +00:00
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [a]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 10:bool/raw <- maybe-convert *x, atom:variant
|
2016-09-17 20:00:39 +00:00
|
|
|
11:@:char/raw <- copy *s2
|
2016-07-23 02:56:18 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is an atom
|
2016-11-22 19:14:43 +00:00
|
|
|
11:array:character <- [a]
|
2016-07-23 02:56:18 +00:00
|
|
|
]
|
|
|
|
]
|
2016-07-23 02:58:30 +00:00
|
|
|
|
|
|
|
scenario parse-atom [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [abc]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 10:bool/raw <- maybe-convert *x, atom:variant
|
2016-09-17 20:00:39 +00:00
|
|
|
11:@:char/raw <- copy *s2
|
2016-07-23 02:58:30 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is an atom
|
2016-11-22 19:14:43 +00:00
|
|
|
11:array:character <- [abc]
|
2016-07-23 02:58:30 +00:00
|
|
|
]
|
|
|
|
]
|
2016-07-23 03:28:51 +00:00
|
|
|
|
2016-07-23 20:54:39 +00:00
|
|
|
scenario parse-list-of-two-atoms [
|
2016-07-23 03:28:51 +00:00
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [(abc def)]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 22:46:59 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < abc | < def | <> > >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
|
|
|
x2:&:cell <- rest x
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 11:bool/raw <- maybe-convert *x1, atom:variant
|
|
|
|
12:bool/raw <- is-pair? x2
|
2016-09-17 19:55:10 +00:00
|
|
|
x3:&:cell <- first x2
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 13:bool/raw <- maybe-convert *x3, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
14:&:cell/raw <- rest x2
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
|
|
|
30:@:char/raw <- copy *s2
|
2016-07-23 03:28:51 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is an atom
|
2016-07-23 20:54:39 +00:00
|
|
|
12 <- 1 # result.rest is a pair
|
|
|
|
13 <- 1 # result.rest.first is an atom
|
|
|
|
14 <- 0 # result.rest.rest is nil
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first
|
|
|
|
30:array:character <- [def] # result.rest.first
|
2016-07-24 22:25:56 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
scenario parse-list-with-extra-spaces [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [ ( abc def ) ] # extra spaces
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 22:46:59 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < abc | < def | <> > >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
|
|
|
x2:&:cell <- rest x
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 11:bool/raw <- maybe-convert *x1, atom:variant
|
|
|
|
12:bool/raw <- is-pair? x2
|
2016-09-17 19:55:10 +00:00
|
|
|
x3:&:cell <- first x2
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 13:bool/raw <- maybe-convert *x3, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
14:&:cell/raw <- rest x2
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
|
|
|
30:@:char/raw <- copy *s2
|
2016-07-24 22:25:56 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is an atom
|
|
|
|
12 <- 1 # result.rest is a pair
|
|
|
|
13 <- 1 # result.rest.first is an atom
|
|
|
|
14 <- 0 # result.rest.rest is nil
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first
|
|
|
|
30:array:character <- [def] # result.rest.first
|
2016-07-23 03:28:51 +00:00
|
|
|
]
|
|
|
|
]
|
2016-07-23 20:54:39 +00:00
|
|
|
|
|
|
|
scenario parse-list-of-more-than-two-atoms [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [(abc def ghi)]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 22:46:59 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < abc | < def | < ghi | <> > > >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
|
|
|
x2:&:cell <- rest x
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 11:bool/raw <- maybe-convert *x1, atom:variant
|
|
|
|
12:bool/raw <- is-pair? x2
|
2016-09-17 19:55:10 +00:00
|
|
|
x3:&:cell <- first x2
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 13:bool/raw <- maybe-convert *x3, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
x4:&:cell <- rest x2
|
2016-10-08 17:52:58 +00:00
|
|
|
14:bool/raw <- is-pair? x4
|
2016-09-17 19:55:10 +00:00
|
|
|
x5:&:cell <- first x4
|
2016-10-08 17:52:58 +00:00
|
|
|
s3:text, 15:bool/raw <- maybe-convert *x5, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
16:&:cell/raw <- rest x4
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
|
|
|
30:@:char/raw <- copy *s2
|
|
|
|
40:@:char/raw <- copy *s3
|
2016-07-23 20:54:39 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is an atom
|
|
|
|
12 <- 1 # result.rest is a pair
|
|
|
|
13 <- 1 # result.rest.first is an atom
|
|
|
|
14 <- 1 # result.rest.rest is a pair
|
|
|
|
15 <- 1 # result.rest.rest.first is an atom
|
|
|
|
16 <- 0 # result.rest.rest.rest is nil
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first
|
|
|
|
30:array:character <- [def] # result.rest.first
|
|
|
|
40:array:character <- [ghi] # result.rest.rest
|
2016-07-23 20:54:39 +00:00
|
|
|
]
|
|
|
|
]
|
2016-07-23 21:17:35 +00:00
|
|
|
|
2016-07-24 22:46:59 +00:00
|
|
|
scenario parse-nested-list [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [((abc))]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 22:46:59 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < < abc | <> > | <> >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
2016-10-08 17:52:58 +00:00
|
|
|
11:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x2:&:cell <- first x1
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 12:bool/raw <- maybe-convert *x2, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
13:&:cell/raw <- rest x1
|
|
|
|
14:&:cell/raw <- rest x
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
2016-07-24 22:46:59 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is a pair
|
|
|
|
12 <- 1 # result.first.first is an atom
|
|
|
|
13 <- 0 # result.first.rest is nil
|
|
|
|
14 <- 0 # result.rest is nil
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first.first
|
2016-07-24 22:46:59 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
scenario parse-nested-list-2 [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [((abc) def)]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 22:46:59 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < < abc | <> > | < def | <> > >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
2016-10-08 17:52:58 +00:00
|
|
|
11:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x2:&:cell <- first x1
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 12:bool/raw <- maybe-convert *x2, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
13:&:cell/raw <- rest x1
|
|
|
|
x3:&:cell <- rest x
|
|
|
|
x4:&:cell <- first x3
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 14:bool/raw <- maybe-convert *x4, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
15:&:cell/raw <- rest x3
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
|
|
|
30:@:char/raw <- copy *s2
|
2016-07-24 22:46:59 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is a pair
|
|
|
|
12 <- 1 # result.first.first is an atom
|
|
|
|
13 <- 0 # result.first.rest is nil
|
|
|
|
14 <- 1 # result.rest.first is an atom
|
|
|
|
15 <- 0 # result.rest.rest is nil
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first.first
|
|
|
|
30:array:character <- [def] # result.rest.first
|
2016-07-24 22:46:59 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2016-07-23 21:17:35 +00:00
|
|
|
# todo: uncomment these tests after we figure out how to continue tests after
|
|
|
|
# assertion failures
|
|
|
|
#? scenario parse-error [
|
|
|
|
#? local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
#? s:text <- new [(]
|
2016-07-23 21:17:35 +00:00
|
|
|
#? #? hide-errors
|
2016-09-17 19:55:10 +00:00
|
|
|
#? x:&:cell <- parse s
|
2016-07-23 21:17:35 +00:00
|
|
|
#? #? show-errors
|
|
|
|
#? trace-should-contain [
|
|
|
|
#? error: unbalanced '(' in expression
|
|
|
|
#? ]
|
|
|
|
#? ]
|
|
|
|
#?
|
|
|
|
#? scenario parse-error-after-element [
|
|
|
|
#? local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
#? s:text <- new [(abc]
|
2016-07-23 21:17:35 +00:00
|
|
|
#? #? hide-errors
|
2016-09-17 19:55:10 +00:00
|
|
|
#? x:&:cell <- parse s
|
2016-07-23 21:17:35 +00:00
|
|
|
#? #? show-errors
|
|
|
|
#? trace-should-contain [
|
|
|
|
#? error: unbalanced '(' in expression
|
|
|
|
#? ]
|
|
|
|
#? ]
|
2016-07-24 23:09:18 +00:00
|
|
|
|
|
|
|
scenario parse-dotted-list-of-two-atoms [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [(abc . def)]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 23:09:18 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < abc | def >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
|
|
|
x2:&:cell <- rest x
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 11:bool/raw <- maybe-convert *x1, atom:variant
|
|
|
|
s2:text, 12:bool/raw <- maybe-convert *x2, atom:variant
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
|
|
|
30:@:char/raw <- copy *s2
|
2016-07-24 23:09:18 +00:00
|
|
|
memory-should-contain [
|
|
|
|
# parses to < abc | def >
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is an atom
|
|
|
|
12 <- 1 # result.rest is an atom
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first
|
|
|
|
30:array:character <- [def] # result.rest
|
2016-07-24 23:09:18 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
scenario parse-dotted-list-of-more-than-two-atoms [
|
|
|
|
local-scope
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- new [(abc def . ghi)]
|
2016-09-17 19:55:10 +00:00
|
|
|
x:&:cell <- parse s
|
2016-07-24 23:09:18 +00:00
|
|
|
trace-should-contain [
|
|
|
|
app/parse: < abc | < def | ghi > >
|
|
|
|
]
|
2016-10-08 17:52:58 +00:00
|
|
|
10:bool/raw <- is-pair? x
|
2016-09-17 19:55:10 +00:00
|
|
|
x1:&:cell <- first x
|
|
|
|
x2:&:cell <- rest x
|
2016-10-08 17:52:58 +00:00
|
|
|
s1:text, 11:bool/raw <- maybe-convert *x1, atom:variant
|
|
|
|
12:bool/raw <- is-pair? x2
|
2016-09-17 19:55:10 +00:00
|
|
|
x3:&:cell <- first x2
|
2016-10-08 17:52:58 +00:00
|
|
|
s2:text, 13:bool/raw <- maybe-convert *x3, atom:variant
|
2016-09-17 19:55:10 +00:00
|
|
|
x4:&:cell <- rest x2
|
2016-10-08 17:52:58 +00:00
|
|
|
s3:text, 14:bool/raw <- maybe-convert *x4, atom:variant
|
2016-09-17 20:00:39 +00:00
|
|
|
20:@:char/raw <- copy *s1
|
|
|
|
30:@:char/raw <- copy *s2
|
|
|
|
40:@:char/raw <- copy *s3
|
2016-07-24 23:09:18 +00:00
|
|
|
memory-should-contain [
|
|
|
|
10 <- 1 # parse result is a pair
|
|
|
|
11 <- 1 # result.first is an atom
|
|
|
|
12 <- 1 # result.rest is a pair
|
|
|
|
13 <- 1 # result.rest.first is an atom
|
|
|
|
14 <- 1 # result.rest.rest is an atom
|
2016-11-22 19:14:43 +00:00
|
|
|
20:array:character <- [abc] # result.first
|
|
|
|
30:array:character <- [def] # result.rest.first
|
|
|
|
40:array:character <- [ghi] # result.rest.rest
|
2016-07-24 23:09:18 +00:00
|
|
|
]
|
|
|
|
]
|
2016-08-07 20:52:48 +00:00
|
|
|
|
2016-10-22 23:56:07 +00:00
|
|
|
## convert tree of cells to Mu text
|
2016-08-07 20:52:48 +00:00
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def to-mu in:&:cell -> out:text [
|
2016-08-07 20:52:48 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2017-04-18 22:44:31 +00:00
|
|
|
buf:&:buffer:char <- new-buffer 30
|
2016-08-07 20:52:48 +00:00
|
|
|
buf <- to-mu in, buf
|
|
|
|
out <- buffer-to-array buf
|
|
|
|
]
|
|
|
|
|
2017-04-18 22:44:31 +00:00
|
|
|
def to-mu in:&:cell, buf:&:buffer:char -> buf:&:buffer:char, result-name:text [
|
2016-08-07 20:52:48 +00:00
|
|
|
local-scope
|
2017-12-04 07:25:40 +00:00
|
|
|
load-inputs
|
2016-08-07 20:52:48 +00:00
|
|
|
# null cell? no change.
|
|
|
|
# pair with all atoms? gensym a new variable
|
|
|
|
# pair containing other pairs? recurse
|
2018-06-17 18:20:53 +00:00
|
|
|
result-name <- copy null
|
2016-08-07 20:52:48 +00:00
|
|
|
]
|