diff options
author | Li Jin <dragon-fly@qq.com> | 2020-01-18 18:15:24 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2020-01-18 18:15:24 +0800 |
commit | 8d1af508f4173e4af6a4ea98584c1a86619f6a20 (patch) | |
tree | 0264c4b01f1152d8114cf46aea6fd773276c0b01 | |
parent | f53ccb373efbf6f6f40284111df309e351c2c18f (diff) | |
download | yuescript-8d1af508f4173e4af6a4ea98584c1a86619f6a20.tar.gz yuescript-8d1af508f4173e4af6a4ea98584c1a86619f6a20.tar.bz2 yuescript-8d1af508f4173e4af6a4ea98584c1a86619f6a20.zip |
fix Moonscript issue 122, add support for ? operator.
-rw-r--r-- | makefile | 2 | ||||
-rw-r--r-- | spec/inputs/assign.moon | 2 | ||||
-rw-r--r-- | spec/inputs/class.moon | 30 | ||||
-rw-r--r-- | spec/inputs/comprehension.moon | 14 | ||||
-rw-r--r-- | spec/inputs/cond.moon | 12 | ||||
-rw-r--r-- | spec/inputs/destructure.moon | 2 | ||||
-rw-r--r-- | spec/inputs/do.moon | 2 | ||||
-rw-r--r-- | spec/inputs/existential.moon | 8 | ||||
-rw-r--r-- | spec/inputs/funcs.moon | 30 | ||||
-rw-r--r-- | spec/inputs/lists.moon | 8 | ||||
-rw-r--r-- | spec/inputs/literals.moon | 62 | ||||
-rw-r--r-- | spec/inputs/local.moon | 2 | ||||
-rw-r--r-- | spec/inputs/loops.moon | 12 | ||||
-rw-r--r-- | spec/inputs/return.moon | 8 | ||||
-rw-r--r-- | spec/inputs/string.moon | 2 | ||||
-rw-r--r-- | spec/inputs/switch.moon | 10 | ||||
-rw-r--r-- | spec/inputs/syntax.moon | 42 | ||||
-rw-r--r-- | spec/inputs/tables.moon | 2 | ||||
-rw-r--r-- | spec/inputs/using.moon | 8 | ||||
-rw-r--r-- | spec/inputs/whitespace.moon | 22 | ||||
-rw-r--r-- | spec/inputs/with.moon | 4 | ||||
-rw-r--r-- | src/MoonP/ast.hpp | 6 | ||||
-rw-r--r-- | src/MoonP/moon_ast.cpp | 1 | ||||
-rw-r--r-- | src/MoonP/moon_ast.h | 5 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 508 | ||||
-rw-r--r-- | src/MoonP/moon_parser.cpp | 15 | ||||
-rw-r--r-- | src/moonc.cpp | 12 |
27 files changed, 523 insertions, 308 deletions
@@ -206,7 +206,7 @@ clean: | |||
206 | .PHONY: test | 206 | .PHONY: test |
207 | test: release | 207 | test: release |
208 | @echo "Compiling Moonscript codes..." | 208 | @echo "Compiling Moonscript codes..." |
209 | @./$(BIN_NAME) $(TEST_INPUT)/*.moon -a -s -t $(TEST_OUTPUT) | 209 | @./$(BIN_NAME) $(TEST_INPUT)/*.moon -l -t $(TEST_OUTPUT) |
210 | 210 | ||
211 | # Main rule, checks the executable and symlinks to the output | 211 | # Main rule, checks the executable and symlinks to the output |
212 | all: $(BIN_PATH)/$(BIN_NAME) | 212 | all: $(BIN_PATH)/$(BIN_NAME) |
diff --git a/spec/inputs/assign.moon b/spec/inputs/assign.moon index 1e5e7a6..3e66491 100644 --- a/spec/inputs/assign.moon +++ b/spec/inputs/assign.moon | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | -> | 2 | _ = -> |
3 | joop = 2302 | 3 | joop = 2302 |
4 | 4 | ||
5 | (hi) -> | 5 | (hi) -> |
diff --git a/spec/inputs/class.moon b/spec/inputs/class.moon index 9a98055..2290bc7 100644 --- a/spec/inputs/class.moon +++ b/spec/inputs/class.moon | |||
@@ -73,11 +73,11 @@ class CoolSuper | |||
73 | hi: => | 73 | hi: => |
74 | super(1,2,3,4) 1,2,3,4 | 74 | super(1,2,3,4) 1,2,3,4 |
75 | super.something 1,2,3,4 | 75 | super.something 1,2,3,4 |
76 | super.something(1,2,3,4).world | 76 | _ = super.something(1,2,3,4).world |
77 | super\yeah"world".okay hi, hi, hi | 77 | super\yeah"world".okay hi, hi, hi |
78 | something.super | 78 | _ = something.super |
79 | super.super.super.super | 79 | _ = super.super.super.super |
80 | super\hello | 80 | _ = super\hello |
81 | nil | 81 | nil |
82 | 82 | ||
83 | 83 | ||
@@ -114,11 +114,11 @@ y = @@ | |||
114 | @ = 343 | 114 | @ = 343 |
115 | @.hello 2,3,4 | 115 | @.hello 2,3,4 |
116 | 116 | ||
117 | hello[@].world | 117 | _ = hello[@].world |
118 | 118 | ||
119 | 119 | ||
120 | class Whacko | 120 | class Whacko |
121 | @hello | 121 | _ = @hello |
122 | if something | 122 | if something |
123 | print "hello world" | 123 | print "hello world" |
124 | 124 | ||
@@ -132,20 +132,20 @@ print "hello" | |||
132 | 132 | ||
133 | yyy = -> | 133 | yyy = -> |
134 | class Cool | 134 | class Cool |
135 | nil | 135 | _ = nil |
136 | 136 | ||
137 | 137 | ||
138 | -- | 138 | -- |
139 | 139 | ||
140 | class a.b.c.D | 140 | class a.b.c.D |
141 | nil | 141 | _ = nil |
142 | 142 | ||
143 | 143 | ||
144 | class a.b["hello"] | 144 | class a.b["hello"] |
145 | nil | 145 | _ = nil |
146 | 146 | ||
147 | class (-> require "moon")!.Something extends Hello.World | 147 | class (-> require "moon")!.Something extends Hello.World |
148 | nil | 148 | _ = nil |
149 | 149 | ||
150 | -- | 150 | -- |
151 | 151 | ||
@@ -160,7 +160,7 @@ print (class WhatsUp).__name | |||
160 | 160 | ||
161 | export ^ | 161 | export ^ |
162 | class Something | 162 | class Something |
163 | nil | 163 | _ = nil |
164 | 164 | ||
165 | 165 | ||
166 | -- | 166 | -- |
@@ -197,17 +197,17 @@ class Whack extends Thing | |||
197 | class Wowha extends Thing | 197 | class Wowha extends Thing |
198 | @butt: -> | 198 | @butt: -> |
199 | super! | 199 | super! |
200 | super.hello | 200 | _ = super.hello |
201 | super\hello! | 201 | super\hello! |
202 | super\hello | 202 | _ = super\hello |
203 | 203 | ||
204 | 204 | ||
205 | @zone: cool { | 205 | @zone: cool { |
206 | -> | 206 | -> |
207 | super! | 207 | super! |
208 | super.hello | 208 | _ = super.hello |
209 | super\hello! | 209 | super\hello! |
210 | super\hello | 210 | _ = super\hello |
211 | } | 211 | } |
212 | 212 | ||
213 | nil | 213 | nil |
diff --git a/spec/inputs/comprehension.moon b/spec/inputs/comprehension.moon index 1609d79..f07cf89 100644 --- a/spec/inputs/comprehension.moon +++ b/spec/inputs/comprehension.moon | |||
@@ -11,11 +11,11 @@ copy = {k,v for k,v in pairs x when k != "okay"} | |||
11 | 11 | ||
12 | -- | 12 | -- |
13 | 13 | ||
14 | { unpack(x) for x in yes } | 14 | _ = { unpack(x) for x in yes } |
15 | { unpack(x) for x in *yes } | 15 | _ = { unpack(x) for x in *yes } |
16 | 16 | ||
17 | { xxxx for x in yes } | 17 | _ = { xxxx for x in yes } |
18 | { unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} } | 18 | _ = { unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} } |
19 | 19 | ||
20 | 20 | ||
21 | -- | 21 | -- |
@@ -28,7 +28,7 @@ bb = [y for thing in y for i=1,10] | |||
28 | cc = [y for i=1,10 for thing in y] | 28 | cc = [y for i=1,10 for thing in y] |
29 | dd = [y for i=1,10 when cool for thing in y when x > 3 when c + 3] | 29 | dd = [y for i=1,10 when cool for thing in y when x > 3 when c + 3] |
30 | 30 | ||
31 | {"hello", "world" for i=1,10} | 31 | _ = {"hello", "world" for i=1,10} |
32 | 32 | ||
33 | -- | 33 | -- |
34 | 34 | ||
@@ -44,8 +44,8 @@ ok(a,b,c) for {a,b,c} in things | |||
44 | 44 | ||
45 | -- | 45 | -- |
46 | 46 | ||
47 | [item for item in *items[1 + 2,3+4]] | 47 | _ = [item for item in *items[1 + 2,3+4]] |
48 | [item for item in *items[hello! * 4, 2 - thing[4]]] | 48 | _ = [item for item in *items[hello! * 4, 2 - thing[4]]] |
49 | 49 | ||
50 | 50 | ||
51 | 51 | ||
diff --git a/spec/inputs/cond.moon b/spec/inputs/cond.moon index 18e42b9..e8b6283 100644 --- a/spec/inputs/cond.moon +++ b/spec/inputs/cond.moon | |||
@@ -1,25 +1,25 @@ | |||
1 | 1 | ||
2 | you_cool = false | 2 | you_cool = false |
3 | 3 | ||
4 | if cool | 4 | _ = if cool |
5 | if you_cool | 5 | if you_cool |
6 | one | 6 | one |
7 | else if eatdic | 7 | else if eatdic |
8 | yeah | 8 | yeah |
9 | else | 9 | else |
10 | two | 10 | _ = two |
11 | three | 11 | three |
12 | else | 12 | else |
13 | no | 13 | no |
14 | 14 | ||
15 | if cool then no | 15 | _ = if cool then no |
16 | if cool then no else yes | 16 | _ = if cool then no else yes |
17 | 17 | ||
18 | if cool then wow cool else | 18 | if cool then wow cool else |
19 | noso cool | 19 | noso cool |
20 | 20 | ||
21 | if working | 21 | if working |
22 | if cool then if cool then okay else what else nah | 22 | _ = if cool then if cool then okay else what else nah |
23 | 23 | ||
24 | 24 | ||
25 | if yeah then no day elseif cool me then okay ya else u way | 25 | if yeah then no day elseif cool me then okay ya else u way |
@@ -70,7 +70,7 @@ hello = 5 + if something = 10 | |||
70 | 70 | ||
71 | z = false | 71 | z = false |
72 | 72 | ||
73 | if false | 73 | _ = if false |
74 | one | 74 | one |
75 | elseif x = true | 75 | elseif x = true |
76 | two | 76 | two |
diff --git a/spec/inputs/destructure.moon b/spec/inputs/destructure.moon index beb79d6..2509968 100644 --- a/spec/inputs/destructure.moon +++ b/spec/inputs/destructure.moon | |||
@@ -90,7 +90,7 @@ do | |||
90 | do | 90 | do |
91 | {a,b,c} = z | 91 | {a,b,c} = z |
92 | 92 | ||
93 | (z) -> | 93 | _ = (z) -> |
94 | {a,b,c} = z | 94 | {a,b,c} = z |
95 | 95 | ||
96 | do | 96 | do |
diff --git a/spec/inputs/do.moon b/spec/inputs/do.moon index 334e68f..21e2127 100644 --- a/spec/inputs/do.moon +++ b/spec/inputs/do.moon | |||
@@ -11,7 +11,7 @@ y = do | |||
11 | things = "shhh" | 11 | things = "shhh" |
12 | -> "hello: " .. things | 12 | -> "hello: " .. things |
13 | 13 | ||
14 | -> if something then do "yeah" | 14 | _ = -> if something then do "yeah" |
15 | 15 | ||
16 | t = { | 16 | t = { |
17 | y: do | 17 | y: do |
diff --git a/spec/inputs/existential.moon b/spec/inputs/existential.moon new file mode 100644 index 0000000..97e8de0 --- /dev/null +++ b/spec/inputs/existential.moon | |||
@@ -0,0 +1,8 @@ | |||
1 | if {:x} = a?.if?\then?(123)? @?\function 998 | ||
2 | print x | ||
3 | |||
4 | with abc?!\func?! | ||
5 | if \p? "abc" | ||
6 | return 123 | ||
7 | |||
8 | @?\func 998 | ||
diff --git a/spec/inputs/funcs.moon b/spec/inputs/funcs.moon index 08a29b6..7a4d5d6 100644 --- a/spec/inputs/funcs.moon +++ b/spec/inputs/funcs.moon | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | x = -> print what | 3 | x = -> print what |
4 | 4 | ||
5 | -> | 5 | _ = -> |
6 | 6 | ||
7 | -> -> -> | 7 | _ = -> -> -> |
8 | 8 | ||
9 | go to the barn | 9 | go to the barn |
10 | 10 | ||
@@ -27,29 +27,29 @@ x = (...) -> | |||
27 | hello! | 27 | hello! |
28 | hello.world! | 28 | hello.world! |
29 | 29 | ||
30 | hello!.something | 30 | _ = hello!.something |
31 | what!["ofefe"] | 31 | _ = what!["ofefe"] |
32 | 32 | ||
33 | what! the! heck! | 33 | what! the! heck! |
34 | 34 | ||
35 | (a,b,c,d,e) -> | 35 | _ = (a,b,c,d,e) -> |
36 | 36 | ||
37 | (a,a,a,a,a) -> | 37 | _ = (a,a,a,a,a) -> |
38 | print a | 38 | print a |
39 | 39 | ||
40 | (x=23023) -> | 40 | _ = (x=23023) -> |
41 | 41 | ||
42 | (x=(y=()->) ->) -> | 42 | _ = (x=(y=()->) ->) -> |
43 | 43 | ||
44 | (x = if something then yeah else no) -> | 44 | _ = (x = if something then yeah else no) -> |
45 | 45 | ||
46 | something = (hello=100, world=(x=[[yeah cool]])-> print "eat rice") -> | 46 | something = (hello=100, world=(x=[[yeah cool]])-> print "eat rice") -> |
47 | print hello | 47 | print hello |
48 | 48 | ||
49 | (x, y) => | 49 | _ = (x, y) => |
50 | (@x, @y) => | 50 | _ = (@x, @y) => |
51 | (x=1) => | 51 | _ = (x=1) => |
52 | (@x=1,y,@z="hello world") => | 52 | _ = (@x=1,y,@z="hello world") => |
53 | 53 | ||
54 | 54 | ||
55 | x -> return | 55 | x -> return |
@@ -57,7 +57,7 @@ y -> return 1 | |||
57 | z -> return 1, "hello", "world" | 57 | z -> return 1, "hello", "world" |
58 | k -> if yes then return else return | 58 | k -> if yes then return else return |
59 | 59 | ||
60 | -> real_name if something | 60 | _ = -> real_name if something |
61 | 61 | ||
62 | -- | 62 | -- |
63 | 63 | ||
@@ -97,7 +97,7 @@ f( | |||
97 | 97 | ||
98 | x = (a, | 98 | x = (a, |
99 | b) -> | 99 | b) -> |
100 | print "what" | 100 | print "what" |
101 | 101 | ||
102 | 102 | ||
103 | y = (a="hi", | 103 | y = (a="hi", |
diff --git a/spec/inputs/lists.moon b/spec/inputs/lists.moon index c119185..e377d5e 100644 --- a/spec/inputs/lists.moon +++ b/spec/inputs/lists.moon | |||
@@ -3,14 +3,14 @@ hi = [x*2 for _, x in ipairs{1,2,3,4}] | |||
3 | 3 | ||
4 | items = {1,2,3,4,5,6} | 4 | items = {1,2,3,4,5,6} |
5 | 5 | ||
6 | [z for z in ipairs items when z > 4] | 6 | _ = [z for z in ipairs items when z > 4] |
7 | 7 | ||
8 | rad = [{a} for a in ipairs { | 8 | rad = [{a} for a in ipairs { |
9 | 1,2,3,4,5,6, | 9 | 1,2,3,4,5,6, |
10 | } when good_number a] | 10 | } when good_number a] |
11 | 11 | ||
12 | 12 | ||
13 | [z for z in items for j in list when z > 4] | 13 | _ = [z for z in items for j in list when z > 4] |
14 | 14 | ||
15 | require "util" | 15 | require "util" |
16 | 16 | ||
@@ -32,7 +32,7 @@ print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2 | |||
32 | 32 | ||
33 | print "hello", x for x in items | 33 | print "hello", x for x in items |
34 | 34 | ||
35 | [x for x in x] | 35 | _ = [x for x in x] |
36 | x = [x for x in x] | 36 | x = [x for x in x] |
37 | 37 | ||
38 | print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2 | 38 | print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2 |
@@ -67,6 +67,6 @@ normal = (hello) -> | |||
67 | test = x 1,2,3,4,5 | 67 | test = x 1,2,3,4,5 |
68 | print thing for thing in *test | 68 | print thing for thing in *test |
69 | 69 | ||
70 | -> a = b for row in *rows | 70 | _ = -> a = b for row in *rows |
71 | 71 | ||
72 | 72 | ||
diff --git a/spec/inputs/literals.moon b/spec/inputs/literals.moon index c3a24a6..d4b0326 100644 --- a/spec/inputs/literals.moon +++ b/spec/inputs/literals.moon | |||
@@ -1,46 +1,46 @@ | |||
1 | 1 | ||
2 | _ = { | ||
3 | 121 | ||
4 | 121.2323 | ||
5 | 121.2323e-1 | ||
6 | 121.2323e13434 | ||
7 | 2323E34 | ||
8 | 0x12323 | ||
2 | 9 | ||
3 | 121 | 10 | 0xfF2323 |
4 | 121.2323 | 11 | 0xabcdef |
5 | 121.2323e-1 | 12 | 0xABCDEF |
6 | 121.2323e13434 | ||
7 | 2323E34 | ||
8 | 0x12323 | ||
9 | 13 | ||
10 | 0xfF2323 | 14 | .2323 |
11 | 0xabcdef | 15 | .2323e-1 |
12 | 0xABCDEF | 16 | .2323e13434 |
13 | 17 | ||
14 | .2323 | ||
15 | .2323e-1 | ||
16 | .2323e13434 | ||
17 | 18 | ||
19 | 1LL | ||
20 | 1ULL | ||
21 | 9332LL | ||
22 | 9332 | ||
23 | 0x2aLL | ||
24 | 0x2aULL | ||
18 | 25 | ||
19 | 1LL | 26 | [[ hello world ]] |
20 | 1ULL | ||
21 | 9332LL | ||
22 | 9332 | ||
23 | 0x2aLL | ||
24 | 0x2aULL | ||
25 | 27 | ||
26 | [[ hello world ]] | 28 | [=[ hello world ]=] |
29 | [====[ hello world ]====] | ||
27 | 30 | ||
28 | [=[ hello world ]=] | 31 | "another world" |
29 | [====[ hello world ]====] | ||
30 | 32 | ||
31 | "another world" | 33 | 'what world' |
32 | 34 | ||
33 | 'what world' | ||
34 | 35 | ||
36 | " | ||
37 | hello world | ||
38 | " | ||
35 | 39 | ||
36 | " | 40 | 'yeah |
37 | hello world | 41 | what is going on |
38 | " | 42 | here is something cool' |
39 | |||
40 | 'yeah | ||
41 | what is going on | ||
42 | here is something cool' | ||
43 | |||
44 | 43 | ||
44 | } | ||
45 | nil | 45 | nil |
46 | 46 | ||
diff --git a/spec/inputs/local.moon b/spec/inputs/local.moon index fec78b1..f14f575 100644 --- a/spec/inputs/local.moon +++ b/spec/inputs/local.moon | |||
@@ -89,6 +89,6 @@ do | |||
89 | do | 89 | do |
90 | local * | 90 | local * |
91 | -- this generates a nil value in the body | 91 | -- this generates a nil value in the body |
92 | for a in *{} do a | 92 | for a in *{} do _ = a |
93 | 93 | ||
94 | g = 2323 -- test if anything leaked | 94 | g = 2323 -- test if anything leaked |
diff --git a/spec/inputs/loops.moon b/spec/inputs/loops.moon index a704e56..130570e 100644 --- a/spec/inputs/loops.moon +++ b/spec/inputs/loops.moon | |||
@@ -33,7 +33,7 @@ for x in y, z, k | |||
33 | 33 | ||
34 | x = -> | 34 | x = -> |
35 | for x in y | 35 | for x in y |
36 | y | 36 | _ = y |
37 | 37 | ||
38 | hello = {1,2,3,4,5} | 38 | hello = {1,2,3,4,5} |
39 | 39 | ||
@@ -43,7 +43,7 @@ x = for y in *hello | |||
43 | 43 | ||
44 | x = -> | 44 | x = -> |
45 | for x in *hello | 45 | for x in *hello |
46 | y | 46 | _ = y |
47 | 47 | ||
48 | t = for i=10,20 do i * 2 | 48 | t = for i=10,20 do i * 2 |
49 | 49 | ||
@@ -52,11 +52,11 @@ y = for j = 3,30, 8 | |||
52 | hmm += 1 | 52 | hmm += 1 |
53 | j * hmm | 53 | j * hmm |
54 | 54 | ||
55 | -> | 55 | _ = -> |
56 | for k=10,40 | 56 | for k=10,40 |
57 | "okay" | 57 | _ = "okay" |
58 | 58 | ||
59 | -> | 59 | _ = -> |
60 | return for k=10,40 | 60 | return for k=10,40 |
61 | "okay" | 61 | "okay" |
62 | 62 | ||
@@ -68,7 +68,7 @@ while 5 + 5 | |||
68 | 68 | ||
69 | while also do | 69 | while also do |
70 | i work too | 70 | i work too |
71 | "okay" | 71 | _ = "okay" |
72 | 72 | ||
73 | i = 0 | 73 | i = 0 |
74 | x = while i < 10 | 74 | x = while i < 10 |
diff --git a/spec/inputs/return.moon b/spec/inputs/return.moon index 61d3dca..98c3104 100644 --- a/spec/inputs/return.moon +++ b/spec/inputs/return.moon | |||
@@ -1,7 +1,7 @@ | |||
1 | -- testing `return` propagation | 1 | -- testing `return` propagation |
2 | 2 | ||
3 | -> x for x in *things | 3 | _ = -> _ = x for x in *things |
4 | -> [x for x in *things] | 4 | _ = -> [x for x in *things] |
5 | 5 | ||
6 | 6 | ||
7 | -- doesn't make sense on purpose | 7 | -- doesn't make sense on purpose |
@@ -14,7 +14,7 @@ do | |||
14 | do | 14 | do |
15 | return {x,y for x,y in *things} | 15 | return {x,y for x,y in *things} |
16 | 16 | ||
17 | -> | 17 | _ = -> |
18 | if a | 18 | if a |
19 | if a | 19 | if a |
20 | a | 20 | a |
@@ -49,7 +49,7 @@ do | |||
49 | else | 49 | else |
50 | b | 50 | b |
51 | 51 | ||
52 | -> a\b | 52 | _ = -> a\b |
53 | do a\b | 53 | do a\b |
54 | 54 | ||
55 | 55 | ||
diff --git a/spec/inputs/string.moon b/spec/inputs/string.moon index 897056a..5d8f772 100644 --- a/spec/inputs/string.moon +++ b/spec/inputs/string.moon | |||
@@ -52,7 +52,7 @@ c = 'hello #{hello}' | |||
52 | 52 | ||
53 | -- | 53 | -- |
54 | 54 | ||
55 | "hello" | 55 | _ = "hello" |
56 | "hello"\format 1 | 56 | "hello"\format 1 |
57 | "hello"\format(1,2,3) | 57 | "hello"\format(1,2,3) |
58 | "hello"\format(1,2,3) 1,2,3 | 58 | "hello"\format(1,2,3) 1,2,3 |
diff --git a/spec/inputs/switch.moon b/spec/inputs/switch.moon index 3bc179b..a028f98 100644 --- a/spec/inputs/switch.moon +++ b/spec/inputs/switch.moon | |||
@@ -15,7 +15,7 @@ switch value | |||
15 | when "cool" | 15 | when "cool" |
16 | print "hello world" | 16 | print "hello world" |
17 | when "yeah" | 17 | when "yeah" |
18 | [[FFFF]] + [[MMMM]] | 18 | _ = [[FFFF]] + [[MMMM]] |
19 | when 2323 + 32434 | 19 | when 2323 + 32434 |
20 | print "okay" | 20 | print "okay" |
21 | else | 21 | else |
@@ -33,9 +33,9 @@ out = switch value | |||
33 | with something | 33 | with something |
34 | switch \value! | 34 | switch \value! |
35 | when .okay | 35 | when .okay |
36 | "world" | 36 | _ = "world" |
37 | else | 37 | else |
38 | "yesh" | 38 | _ = "yesh" |
39 | 39 | ||
40 | fix this | 40 | fix this |
41 | call_func switch something | 41 | call_func switch something |
@@ -46,7 +46,7 @@ call_func switch something | |||
46 | 46 | ||
47 | switch hi | 47 | switch hi |
48 | when hello or world | 48 | when hello or world |
49 | greene | 49 | _ = greene |
50 | 50 | ||
51 | -- | 51 | -- |
52 | 52 | ||
@@ -54,7 +54,7 @@ switch hi | |||
54 | when "one", "two" | 54 | when "one", "two" |
55 | print "cool" | 55 | print "cool" |
56 | when "dad" | 56 | when "dad" |
57 | no | 57 | _ = no |
58 | 58 | ||
59 | switch hi | 59 | switch hi |
60 | when 3+1, hello!, (-> 4)! | 60 | when 3+1, hello!, (-> 4)! |
diff --git a/spec/inputs/syntax.moon b/spec/inputs/syntax.moon index 854f629..351b22c 100644 --- a/spec/inputs/syntax.moon +++ b/spec/inputs/syntax.moon | |||
@@ -27,7 +27,7 @@ what(the)[3243] world, yeck heck | |||
27 | 27 | ||
28 | hairy[hands][are](gross) okay okay[world] | 28 | hairy[hands][are](gross) okay okay[world] |
29 | 29 | ||
30 | (get[something] + 5)[years] | 30 | _ = (get[something] + 5)[years] |
31 | 31 | ||
32 | i,x = 200, 300 | 32 | i,x = 200, 300 |
33 | 33 | ||
@@ -37,27 +37,27 @@ yeah = ((1+5)*3)/2 + i % 100 | |||
37 | 37 | ||
38 | whoa = (1+2) * (3+4) * (4+5) | 38 | whoa = (1+2) * (3+4) * (4+5) |
39 | 39 | ||
40 | -> | 40 | _ = -> |
41 | if something | 41 | if something |
42 | return 1,2,4 | 42 | return 1,2,4 |
43 | 43 | ||
44 | print "hello" | 44 | print "hello" |
45 | 45 | ||
46 | -> | 46 | _ = -> |
47 | if hello | 47 | if hello |
48 | "heloo", "world" | 48 | "heloo", "world" |
49 | else | 49 | else |
50 | no, way | 50 | no, way |
51 | 51 | ||
52 | 52 | ||
53 | -> 1,2,34 | 53 | _ = -> 1,2,34 |
54 | 54 | ||
55 | return 5 + () -> 4 + 2 | 55 | return 5 + () -> 4 + 2 |
56 | 56 | ||
57 | return 5 + (() -> 4) + 2 | 57 | return 5 + (() -> 4) + 2 |
58 | 58 | ||
59 | print 5 + () -> | 59 | print 5 + () -> |
60 | 34 | 60 | _ = 34 |
61 | good nads | 61 | good nads |
62 | 62 | ||
63 | 63 | ||
@@ -66,19 +66,19 @@ something 'else', "ya" | |||
66 | something'else' | 66 | something'else' |
67 | something"else" | 67 | something"else" |
68 | 68 | ||
69 | something[[hey]] * 2 | 69 | _ = something[[hey]] * 2 |
70 | something[======[hey]======] * 2 | 70 | _ = something[======[hey]======] * 2 |
71 | 71 | ||
72 | 72 | ||
73 | something'else', 2 | 73 | _ = something'else', 2 |
74 | something"else", 2 | 74 | _ = something"else", 2 |
75 | something[[else]], 2 | 75 | _ = something[[else]], 2 |
76 | 76 | ||
77 | something 'else', 2 | 77 | something 'else', 2 |
78 | something "else", 2 | 78 | something "else", 2 |
79 | something [[else]], 2 | 79 | something [[else]], 2 |
80 | 80 | ||
81 | here(we)"go"[12123] | 81 | _ = here(we)"go"[12123] |
82 | 82 | ||
83 | -- this runs | 83 | -- this runs |
84 | something = | 84 | something = |
@@ -120,9 +120,9 @@ print "hello" for i=1,10 | |||
120 | 120 | ||
121 | print "nutjob" | 121 | print "nutjob" |
122 | 122 | ||
123 | if hello then 343 | 123 | if hello then _ = 343 |
124 | 124 | ||
125 | print "what" if cool else whack | 125 | print "what" if cool else whack! |
126 | 126 | ||
127 | arg = {...} | 127 | arg = {...} |
128 | 128 | ||
@@ -139,7 +139,7 @@ y = #"hello" | |||
139 | 139 | ||
140 | x = #{#{},#{1},#{1,2}} | 140 | x = #{#{},#{1},#{1,2}} |
141 | 141 | ||
142 | hello, world | 142 | _ = hello, world |
143 | 143 | ||
144 | something\hello(what) a,b | 144 | something\hello(what) a,b |
145 | something\hello what | 145 | something\hello what |
@@ -163,7 +163,7 @@ a["hello#{tostring ff}"] += 10 | |||
163 | a[four].x += 10 | 163 | a[four].x += 10 |
164 | 164 | ||
165 | x = 0 | 165 | x = 0 |
166 | (if ntype(v) == "fndef" then x += 1) for v in *values | 166 | _ = (if ntype(v) == "fndef" then x += 1) for v in *values |
167 | 167 | ||
168 | 168 | ||
169 | hello = | 169 | hello = |
@@ -176,10 +176,10 @@ hello = | |||
176 | 176 | ||
177 | div class: "cool" | 177 | div class: "cool" |
178 | 178 | ||
179 | 5 + what wack | 179 | _ = 5 + what wack |
180 | what whack + 5 | 180 | what whack + 5 |
181 | 181 | ||
182 | 5 - what wack | 182 | _ = 5 - what wack |
183 | what whack - 5 | 183 | what whack - 5 |
184 | 184 | ||
185 | x = hello - world - something | 185 | x = hello - world - something |
@@ -189,16 +189,16 @@ x = hello - world - something | |||
189 | print something)! | 189 | print something)! |
190 | 190 | ||
191 | if something | 191 | if something |
192 | 03589 | 192 | _ = 03589 |
193 | 193 | ||
194 | -- okay what about this | 194 | -- okay what about this |
195 | 195 | ||
196 | else | 196 | else |
197 | 3434 | 197 | _ = 3434 |
198 | 198 | ||
199 | 199 | ||
200 | if something | 200 | if something |
201 | yeah | 201 | _ = yeah |
202 | 202 | ||
203 | 203 | ||
204 | elseif "ymmm" | 204 | elseif "ymmm" |
@@ -207,7 +207,7 @@ elseif "ymmm" | |||
207 | 207 | ||
208 | else | 208 | else |
209 | 209 | ||
210 | okay | 210 | _ = okay |
211 | 211 | ||
212 | 212 | ||
213 | -- test names containing keywords | 213 | -- test names containing keywords |
diff --git a/spec/inputs/tables.moon b/spec/inputs/tables.moon index 2bf66d7..10bccde 100644 --- a/spec/inputs/tables.moon +++ b/spec/inputs/tables.moon | |||
@@ -138,7 +138,7 @@ thing what: | |||
138 | thing what: | 138 | thing what: |
139 | "great", no: | 139 | "great", no: |
140 | "more" | 140 | "more" |
141 | okay: 123 -- a anon table | 141 | _ = okay: 123 -- a anon table |
142 | 142 | ||
143 | 143 | ||
144 | -- | 144 | -- |
diff --git a/spec/inputs/using.moon b/spec/inputs/using.moon index 55a16a7..e407983 100644 --- a/spec/inputs/using.moon +++ b/spec/inputs/using.moon | |||
@@ -2,18 +2,18 @@ | |||
2 | hello = "hello" | 2 | hello = "hello" |
3 | world = "world" | 3 | world = "world" |
4 | 4 | ||
5 | (using nil) -> | 5 | _ = (using nil) -> |
6 | hello = 3223 | 6 | hello = 3223 |
7 | 7 | ||
8 | (a using nil) -> | 8 | _ = (a using nil) -> |
9 | hello = 3223 | 9 | hello = 3223 |
10 | a = 323 | 10 | a = 323 |
11 | 11 | ||
12 | (a,b,c using a,b,c) -> | 12 | _ = (a,b,c using a,b,c) -> |
13 | a,b,c = 1,2,3 | 13 | a,b,c = 1,2,3 |
14 | world = 12321 | 14 | world = 12321 |
15 | 15 | ||
16 | (a,e,f using a,b,c, hello) -> | 16 | _ = (a,e,f using a,b,c, hello) -> |
17 | a,b,c = 1,2,3 | 17 | a,b,c = 1,2,3 |
18 | hello = 12321 | 18 | hello = 12321 |
19 | world = "yeah" | 19 | world = "yeah" |
diff --git a/spec/inputs/whitespace.moon b/spec/inputs/whitespace.moon index 4a2ff1f..e505b1b 100644 --- a/spec/inputs/whitespace.moon +++ b/spec/inputs/whitespace.moon | |||
@@ -1,42 +1,42 @@ | |||
1 | 1 | ||
2 | { | 2 | _ = { |
3 | 1, 2 | 3 | 1, 2 |
4 | } | 4 | } |
5 | 5 | ||
6 | { 1, 2 | 6 | _ = { 1, 2 |
7 | } | 7 | } |
8 | 8 | ||
9 | { 1, 2 } | 9 | _ = { 1, 2 } |
10 | 10 | ||
11 | {1,2} | 11 | _ = {1,2} |
12 | 12 | ||
13 | { | 13 | _ = { |
14 | 1,2 | 14 | 1,2 |
15 | 15 | ||
16 | } | 16 | } |
17 | 17 | ||
18 | { something 1,2, | 18 | _ = { something 1,2, |
19 | 4,5,6, | 19 | 4,5,6, |
20 | 3,4,5 | 20 | 3,4,5 |
21 | } | 21 | } |
22 | 22 | ||
23 | { | 23 | _ = { |
24 | a 1,2,3, | 24 | a 1,2,3, |
25 | 4,5,6 | 25 | 4,5,6 |
26 | 1,2,3 | 26 | 1,2,3 |
27 | } | 27 | } |
28 | 28 | ||
29 | 29 | ||
30 | { | 30 | _ = { |
31 | b 1,2,3, | 31 | b 1,2,3, |
32 | 4,5,6 | 32 | 4,5,6 |
33 | 1,2,3, | 33 | 1,2,3, |
34 | 1,2,3 | 34 | 1,2,3 |
35 | } | 35 | } |
36 | 36 | ||
37 | { 1,2,3 } | 37 | _ = { 1,2,3 } |
38 | 38 | ||
39 | { c 1,2,3, | 39 | _ = { c 1,2,3, |
40 | } | 40 | } |
41 | 41 | ||
42 | 42 | ||
@@ -58,7 +58,7 @@ hello 1,2,3, | |||
58 | 9,9 | 58 | 9,9 |
59 | 59 | ||
60 | 60 | ||
61 | { | 61 | _ = { |
62 | hello 1,2, | 62 | hello 1,2, |
63 | 3,4, | 63 | 3,4, |
64 | 5, 6 | 64 | 5, 6 |
diff --git a/spec/inputs/with.moon b/spec/inputs/with.moon index ae3c8c0..f543356 100644 --- a/spec/inputs/with.moon +++ b/spec/inputs/with.moon | |||
@@ -37,7 +37,7 @@ do | |||
37 | 37 | ||
38 | do | 38 | do |
39 | with foo | 39 | with foo |
40 | \prop"something".hello | 40 | _ = \prop"something".hello |
41 | .prop\send(one) | 41 | .prop\send(one) |
42 | .prop\send one | 42 | .prop\send one |
43 | 43 | ||
@@ -107,7 +107,7 @@ do | |||
107 | print .c | 107 | print .c |
108 | 108 | ||
109 | do | 109 | do |
110 | -> | 110 | _ = -> |
111 | with hi | 111 | with hi |
112 | return .a, .b | 112 | return .a, .b |
113 | 113 | ||
diff --git a/src/MoonP/ast.hpp b/src/MoonP/ast.hpp index f2ef76c..0b5ffca 100644 --- a/src/MoonP/ast.hpp +++ b/src/MoonP/ast.hpp | |||
@@ -392,6 +392,12 @@ public: | |||
392 | node->release(); | 392 | node->release(); |
393 | } | 393 | } |
394 | 394 | ||
395 | void pop_back() { | ||
396 | auto node = m_objects.back(); | ||
397 | m_objects.pop_back(); | ||
398 | node->release(); | ||
399 | } | ||
400 | |||
395 | const node_container& objects() const { | 401 | const node_container& objects() const { |
396 | return m_objects; | 402 | return m_objects; |
397 | } | 403 | } |
diff --git a/src/MoonP/moon_ast.cpp b/src/MoonP/moon_ast.cpp index 0ccd0ed..f3fe31e 100644 --- a/src/MoonP/moon_ast.cpp +++ b/src/MoonP/moon_ast.cpp | |||
@@ -79,6 +79,7 @@ AST_IMPL(ColonChainItem) | |||
79 | AST_IMPL(default_value) | 79 | AST_IMPL(default_value) |
80 | AST_IMPL(Slice) | 80 | AST_IMPL(Slice) |
81 | AST_IMPL(Invoke) | 81 | AST_IMPL(Invoke) |
82 | AST_IMPL(existential_op) | ||
82 | AST_IMPL(TableLit) | 83 | AST_IMPL(TableLit) |
83 | AST_IMPL(TableBlock) | 84 | AST_IMPL(TableBlock) |
84 | AST_IMPL(class_member_list) | 85 | AST_IMPL(class_member_list) |
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index a614465..8b80af3 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h | |||
@@ -407,11 +407,14 @@ AST_NODE(Invoke, "Invoke"_id) | |||
407 | AST_MEMBER(Invoke, &sep, &args) | 407 | AST_MEMBER(Invoke, &sep, &args) |
408 | AST_END(Invoke) | 408 | AST_END(Invoke) |
409 | 409 | ||
410 | AST_LEAF(existential_op, "existential_op"_id) | ||
411 | AST_END(existential_op) | ||
412 | |||
410 | class InvokeArgs_t; | 413 | class InvokeArgs_t; |
411 | 414 | ||
412 | AST_NODE(ChainValue, "ChainValue"_id) | 415 | AST_NODE(ChainValue, "ChainValue"_id) |
413 | ast_ptr<true, Seperator_t> sep; | 416 | ast_ptr<true, Seperator_t> sep; |
414 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t> items; | 417 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t> items; |
415 | AST_MEMBER(ChainValue, &sep, &items) | 418 | AST_MEMBER(ChainValue, &sep, &items) |
416 | AST_END(ChainValue) | 419 | AST_END(ChainValue) |
417 | 420 | ||
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index d30f413..9164f6a 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
15 | #include <memory> | 15 | #include <memory> |
16 | #include <sstream> | 16 | #include <sstream> |
17 | #include <string_view> | 17 | #include <string_view> |
18 | #include <iostream> | ||
18 | using namespace std::string_view_literals; | 19 | using namespace std::string_view_literals; |
19 | #include "MoonP/parser.hpp" | 20 | #include "MoonP/parser.hpp" |
20 | #include "MoonP/moon_ast.h" | 21 | #include "MoonP/moon_ast.h" |
@@ -426,6 +427,35 @@ private: | |||
426 | return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); | 427 | return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); |
427 | } | 428 | } |
428 | 429 | ||
430 | bool isSpecialChainValue(ChainValue_t* chainValue) { | ||
431 | if (ast_is<ColonChainItem_t>(chainValue->items.back())) { | ||
432 | return true; | ||
433 | } | ||
434 | for (auto item : chainValue->items.objects()) { | ||
435 | if (auto colonChain = ast_cast<ColonChainItem_t>(item)) { | ||
436 | if (ast_is<LuaKeyword_t>(colonChain->name)) { | ||
437 | return true; | ||
438 | } | ||
439 | } else if (ast_is<existential_op_t>(item) && item != chainValue->items.back()) { | ||
440 | return true; | ||
441 | } | ||
442 | } | ||
443 | return false; | ||
444 | } | ||
445 | |||
446 | std::string singleVariableFrom(ChainValue_t* chainValue) { | ||
447 | BLOCK_START | ||
448 | BREAK_IF(!chainValue); | ||
449 | BREAK_IF(chainValue->items.size() != 1); | ||
450 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | ||
451 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); | ||
452 | str_list tmp; | ||
453 | transformCallable(callable, tmp); | ||
454 | return tmp.back(); | ||
455 | BLOCK_END | ||
456 | return Empty; | ||
457 | } | ||
458 | |||
429 | std::string singleVariableFrom(ast_node* expList) { | 459 | std::string singleVariableFrom(ast_node* expList) { |
430 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; | 460 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; |
431 | BLOCK_START | 461 | BLOCK_START |
@@ -435,7 +465,7 @@ private: | |||
435 | BREAK_IF(!chainValue); | 465 | BREAK_IF(!chainValue); |
436 | BREAK_IF(chainValue->items.size() != 1); | 466 | BREAK_IF(chainValue->items.size() != 1); |
437 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | 467 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); |
438 | BREAK_IF(!callable || !callable->item.is<Variable_t>()); | 468 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); |
439 | str_list tmp; | 469 | str_list tmp; |
440 | transformCallable(callable, tmp); | 470 | transformCallable(callable, tmp); |
441 | return tmp.back(); | 471 | return tmp.back(); |
@@ -443,22 +473,6 @@ private: | |||
443 | return Empty; | 473 | return Empty; |
444 | } | 474 | } |
445 | 475 | ||
446 | bool isColonChain(ChainValue_t* chainValue) { | ||
447 | return ast_is<ColonChainItem_t>(chainValue->items.back()); | ||
448 | } | ||
449 | |||
450 | bool hasKeywordColonChainItem(ChainValue_t* chainValue) { | ||
451 | const auto& chainList = chainValue->items.objects(); | ||
452 | for (auto it = chainList.begin(); it != chainList.end(); ++it) { | ||
453 | if (auto colonItem = ast_cast<ColonChainItem_t>(*it)) { | ||
454 | if (colonItem->name.is<LuaKeyword_t>()) { | ||
455 | return true; | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | return false; | ||
460 | } | ||
461 | |||
462 | bool isAssignable(const node_container& chainItems) { | 476 | bool isAssignable(const node_container& chainItems) { |
463 | if (chainItems.size() == 1) { | 477 | if (chainItems.size() == 1) { |
464 | auto firstItem = chainItems.back(); | 478 | auto firstItem = chainItems.back(); |
@@ -539,7 +553,7 @@ private: | |||
539 | } | 553 | } |
540 | auto line = _converter.to_bytes(std::wstring(begin, end)); | 554 | auto line = _converter.to_bytes(std::wstring(begin, end)); |
541 | int oldCol = loc->m_begin.m_col; | 555 | int oldCol = loc->m_begin.m_col; |
542 | int col = loc->m_begin.m_col - 1; | 556 | int col = std::max(0, oldCol - 1); |
543 | auto it = begin; | 557 | auto it = begin; |
544 | for (int i = 0; i < oldCol; ++i) { | 558 | for (int i = 0; i < oldCol; ++i) { |
545 | if (*it > ASCII) { | 559 | if (*it > ASCII) { |
@@ -558,7 +572,7 @@ private: | |||
558 | auto x = statement; | 572 | auto x = statement; |
559 | if (statement->appendix) { | 573 | if (statement->appendix) { |
560 | if (auto assignment = assignmentFrom(statement)) { | 574 | if (auto assignment = assignmentFrom(statement)) { |
561 | auto preDefine = getPredefine(transformAssignDefs(assignment->expList)); | 575 | auto preDefine = getPredefine(assignment); |
562 | if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); | 576 | if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); |
563 | } | 577 | } |
564 | auto appendix = statement->appendix.get(); | 578 | auto appendix = statement->appendix.get(); |
@@ -790,7 +804,7 @@ private: | |||
790 | } | 804 | } |
791 | 805 | ||
792 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 806 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
793 | auto info = extractDestructureInfo(assignment); | 807 | auto info = extractDestructureInfo(assignment, true); |
794 | if (!info.first.empty()) { | 808 | if (!info.first.empty()) { |
795 | for (const auto& destruct : info.first) { | 809 | for (const auto& destruct : info.first) { |
796 | str_list defs; | 810 | str_list defs; |
@@ -909,11 +923,10 @@ private: | |||
909 | } | 923 | } |
910 | case "With"_id: { | 924 | case "With"_id: { |
911 | auto withNode = static_cast<With_t*>(value); | 925 | auto withNode = static_cast<With_t*>(value); |
912 | str_list temp; | ||
913 | auto expList = assignment->expList.get(); | 926 | auto expList = assignment->expList.get(); |
914 | std::string preDefine = getPredefine(assignment); | 927 | std::string preDefine = getPredefine(assignment); |
915 | transformWith(withNode, temp, expList); | 928 | transformWith(withNode, out, expList); |
916 | out.push_back(preDefine + temp.back()); | 929 | out.back() = preDefine + out.back(); |
917 | return; | 930 | return; |
918 | } | 931 | } |
919 | case "Do"_id: { | 932 | case "Do"_id: { |
@@ -940,50 +953,42 @@ private: | |||
940 | return; | 953 | return; |
941 | } | 954 | } |
942 | case "For"_id: { | 955 | case "For"_id: { |
943 | str_list temp; | ||
944 | auto expList = assignment->expList.get(); | 956 | auto expList = assignment->expList.get(); |
945 | std::string preDefine = getPredefine(assignment); | 957 | std::string preDefine = getPredefine(assignment); |
946 | transformForInPlace(static_cast<For_t*>(value), temp, expList); | 958 | transformForInPlace(static_cast<For_t*>(value), out, expList); |
947 | out.push_back(preDefine + temp.back()); | 959 | out.back() = preDefine + out.back(); |
948 | return; | 960 | return; |
949 | } | 961 | } |
950 | case "ForEach"_id: { | 962 | case "ForEach"_id: { |
951 | str_list temp; | ||
952 | auto expList = assignment->expList.get(); | 963 | auto expList = assignment->expList.get(); |
953 | std::string preDefine = getPredefine(assignment); | 964 | std::string preDefine = getPredefine(assignment); |
954 | transformForEachInPlace(static_cast<ForEach_t*>(value), temp, expList); | 965 | transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList); |
955 | out.push_back(preDefine + temp.back()); | 966 | out.back() = preDefine + out.back(); |
956 | return; | 967 | return; |
957 | } | 968 | } |
958 | case "ClassDecl"_id: { | 969 | case "ClassDecl"_id: { |
959 | str_list temp; | ||
960 | auto expList = assignment->expList.get(); | 970 | auto expList = assignment->expList.get(); |
961 | std::string preDefine = getPredefine(assignment); | 971 | std::string preDefine = getPredefine(assignment); |
962 | transformClassDecl(static_cast<ClassDecl_t*>(value), temp, ExpUsage::Assignment, expList); | 972 | transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList); |
963 | out.push_back(preDefine + temp.back()); | 973 | out.back() = preDefine + out.back(); |
964 | return; | 974 | return; |
965 | } | 975 | } |
966 | case "While"_id: { | 976 | case "While"_id: { |
967 | str_list temp; | ||
968 | auto expList = assignment->expList.get(); | 977 | auto expList = assignment->expList.get(); |
969 | std::string preDefine = getPredefine(assignment); | 978 | std::string preDefine = getPredefine(assignment); |
970 | transformWhileInPlace(static_cast<While_t*>(value), temp, expList); | 979 | transformWhileInPlace(static_cast<While_t*>(value), out, expList); |
971 | out.push_back(preDefine + temp.back()); | 980 | out.back() = preDefine + out.back(); |
972 | return; | 981 | return; |
973 | } | 982 | } |
974 | } | 983 | } |
975 | auto exp = ast_cast<Exp_t>(value); | 984 | auto exp = ast_cast<Exp_t>(value); |
976 | BREAK_IF(!exp); | 985 | BREAK_IF(!exp); |
977 | if (auto chainValue = exp->value->item.as<ChainValue_t>()) { | 986 | if (auto chainValue = exp->value->item.as<ChainValue_t>()) { |
978 | if (isColonChain(chainValue)) { | 987 | if (isSpecialChainValue(chainValue)) { |
979 | auto assignable = assignment->expList.get(); | 988 | auto expList = assignment->expList.get(); |
980 | std::string preDefine = getPredefine(transformAssignDefs(assignable)); | 989 | std::string preDefine = getPredefine(assignment); |
981 | transformColonChain(chainValue, out, ExpUsage::Assignment, assignable); | 990 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList); |
982 | auto nl = preDefine.empty() ? Empty : nll(chainValue); | 991 | out.back() = preDefine + out.back(); |
983 | if (!preDefine.empty()) out.back() = preDefine + nl + out.back(); | ||
984 | return; | ||
985 | } else if (hasKeywordColonChainItem(chainValue)) { | ||
986 | transformChainValue(chainValue, out, ExpUsage::Assignment, assignment->expList); | ||
987 | return; | 992 | return; |
988 | } | 993 | } |
989 | } | 994 | } |
@@ -1169,7 +1174,7 @@ private: | |||
1169 | } | 1174 | } |
1170 | 1175 | ||
1171 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 1176 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> |
1172 | extractDestructureInfo(ExpListAssign_t* assignment) { | 1177 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly = false) { |
1173 | auto x = assignment; | 1178 | auto x = assignment; |
1174 | std::list<Destructure> destructs; | 1179 | std::list<Destructure> destructs; |
1175 | if (!assignment->action.is<Assign_t>()) return { destructs, nullptr }; | 1180 | if (!assignment->action.is<Assign_t>()) return { destructs, nullptr }; |
@@ -1187,19 +1192,21 @@ private: | |||
1187 | while (values.size() < size) values.emplace_back(nullNode); | 1192 | while (values.size() < size) values.emplace_back(nullNode); |
1188 | } | 1193 | } |
1189 | using iter = node_container::iterator; | 1194 | using iter = node_container::iterator; |
1190 | std::vector<std::pair<iter, iter>> destructPairs; | 1195 | std::vector<std::pair<iter,iter>> destructPairs; |
1191 | str_list temp; | 1196 | str_list temp; |
1192 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { | 1197 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { |
1193 | auto expr = *i; | 1198 | auto expr = *i; |
1194 | ast_node* destructNode = expr->getByPath<Value_t, SimpleValue_t, TableLit_t>(); | 1199 | ast_node* destructNode = expr->getByPath<Value_t, SimpleValue_t, TableLit_t>(); |
1195 | if (destructNode || (destructNode = expr->getByPath<Value_t, simple_table_t>())) { | 1200 | if (destructNode || (destructNode = expr->getByPath<Value_t, simple_table_t>())) { |
1196 | destructPairs.push_back({i,j}); | 1201 | destructPairs.push_back({i,j}); |
1197 | pushScope(); | ||
1198 | transformAssignItem(*j, temp); | ||
1199 | popScope(); | ||
1200 | auto& destruct = destructs.emplace_back(); | 1202 | auto& destruct = destructs.emplace_back(); |
1201 | destruct.value = temp.back(); | 1203 | if (!varDefOnly) { |
1202 | temp.pop_back(); | 1204 | pushScope(); |
1205 | transformAssignItem(*j, temp); | ||
1206 | destruct.value = temp.back(); | ||
1207 | temp.pop_back(); | ||
1208 | popScope(); | ||
1209 | } | ||
1203 | auto pairs = destructFromExp(expr); | 1210 | auto pairs = destructFromExp(expr); |
1204 | destruct.items = std::move(pairs); | 1211 | destruct.items = std::move(pairs); |
1205 | } | 1212 | } |
@@ -1244,7 +1251,7 @@ private: | |||
1244 | BREAK_IF(!exp); | 1251 | BREAK_IF(!exp); |
1245 | auto var = singleVariableFrom(exp); | 1252 | auto var = singleVariableFrom(exp); |
1246 | BREAK_IF(!var.empty()); | 1253 | BREAK_IF(!var.empty()); |
1247 | auto upVar = getUnusedName("_update_"); | 1254 | auto upVar = getUnusedName("_update_"sv); |
1248 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 1255 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
1249 | assignment->expList.set(toAst<ExpList_t>(upVar, ExpList, x)); | 1256 | assignment->expList.set(toAst<ExpList_t>(upVar, ExpList, x)); |
1250 | auto assign = x->new_ptr<Assign_t>(); | 1257 | auto assign = x->new_ptr<Assign_t>(); |
@@ -1532,11 +1539,7 @@ private: | |||
1532 | case "simple_table"_id: transform_simple_table(static_cast<simple_table_t*>(item), out); break; | 1539 | case "simple_table"_id: transform_simple_table(static_cast<simple_table_t*>(item), out); break; |
1533 | case "ChainValue"_id: { | 1540 | case "ChainValue"_id: { |
1534 | auto chainValue = static_cast<ChainValue_t*>(item); | 1541 | auto chainValue = static_cast<ChainValue_t*>(item); |
1535 | if (isColonChain(chainValue)) { | 1542 | transformChainValue(chainValue, out); |
1536 | transformColonChainClosure(chainValue, out); | ||
1537 | } else { | ||
1538 | transformChainValue(chainValue, out); | ||
1539 | } | ||
1540 | break; | 1543 | break; |
1541 | } | 1544 | } |
1542 | case "String"_id: transformString(static_cast<String_t*>(item), out); break; | 1545 | case "String"_id: transformString(static_cast<String_t*>(item), out); break; |
@@ -1689,7 +1692,7 @@ private: | |||
1689 | any->decls.push_back(var); | 1692 | any->decls.push_back(var); |
1690 | } | 1693 | } |
1691 | } | 1694 | } |
1692 | auto info = extractDestructureInfo(assignment); | 1695 | auto info = extractDestructureInfo(assignment, true); |
1693 | if (!info.first.empty()) { | 1696 | if (!info.first.empty()) { |
1694 | for (const auto& destruct : info.first) | 1697 | for (const auto& destruct : info.first) |
1695 | for (const auto& item : destruct.items) | 1698 | for (const auto& item : destruct.items) |
@@ -1803,12 +1806,10 @@ private: | |||
1803 | } | 1806 | } |
1804 | } | 1807 | } |
1805 | if (auto chainValue = singleValue->item.as<ChainValue_t>()) { | 1808 | if (auto chainValue = singleValue->item.as<ChainValue_t>()) { |
1806 | if (isColonChain(chainValue)) { | 1809 | if (isSpecialChainValue(chainValue)) { |
1807 | transformColonChain(chainValue, out, ExpUsage::Return); | ||
1808 | } else { | ||
1809 | transformChainValue(chainValue, out, ExpUsage::Return); | 1810 | transformChainValue(chainValue, out, ExpUsage::Return); |
1811 | return; | ||
1810 | } | 1812 | } |
1811 | return; | ||
1812 | } | 1813 | } |
1813 | transformValue(singleValue, out); | 1814 | transformValue(singleValue, out); |
1814 | out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); | 1815 | out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); |
@@ -1980,111 +1981,292 @@ private: | |||
1980 | } | 1981 | } |
1981 | } | 1982 | } |
1982 | 1983 | ||
1983 | void transformColonChainClosure(ChainValue_t* chainValue, str_list& out) { | 1984 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t*) { |
1984 | str_list temp; | 1985 | auto x = chainList.front(); |
1985 | temp.push_back(s("(function()"sv) + nll(chainValue)); | 1986 | if (ast_cast<existential_op_t>(chainList.back())) { |
1986 | pushScope(); | 1987 | auto parens = x->new_ptr<Parens_t>(); |
1987 | transformColonChain(chainValue, temp, ExpUsage::Return); | 1988 | { |
1988 | popScope(); | 1989 | auto chainValue = x->new_ptr<ChainValue_t>(); |
1989 | temp.push_back(indent() + s("end)()"sv)); | 1990 | for (auto item : chainList) { |
1990 | out.push_back(join(temp)); | 1991 | chainValue->items.push_back(item); |
1992 | } | ||
1993 | chainValue->items.pop_back(); | ||
1994 | auto value = x->new_ptr<Value_t>(); | ||
1995 | value->item.set(chainValue); | ||
1996 | auto opValue = x->new_ptr<exp_op_value_t>(); | ||
1997 | opValue->op.set(toAst<BinaryOperator_t>("!="sv, BinaryOperator, x)); | ||
1998 | opValue->value.set(toAst<Value_t>("nil"sv, Value, x)); | ||
1999 | auto exp = x->new_ptr<Exp_t>(); | ||
2000 | exp->value.set(value); | ||
2001 | exp->opValues.push_back(opValue); | ||
2002 | parens->expr.set(exp); | ||
2003 | } | ||
2004 | transformParens(parens, out); | ||
2005 | if (usage == ExpUsage::Return) { | ||
2006 | out.back().insert(0, indent() + s("return "sv)); | ||
2007 | out.back().append(nlr(x)); | ||
2008 | } | ||
2009 | return true; | ||
2010 | } | ||
2011 | return false; | ||
1991 | } | 2012 | } |
1992 | 2013 | ||
1993 | void transformColonChain(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Common, ExpList_t* expList = nullptr) { | 2014 | bool transformChainWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
1994 | auto x = chainValue; | 2015 | auto opIt = std::find_if(chainList.begin(), chainList.end(), [](ast_node* node) { return ast_is<existential_op_t>(node); }); |
1995 | const auto& chainList = chainValue->items.objects(); | 2016 | if (opIt != chainList.end()) { |
1996 | auto baseChain = x->new_ptr<ChainValue_t>(); | 2017 | auto x = chainList.front(); |
1997 | switch (chainList.front()->getId()) { | 2018 | str_list temp; |
1998 | case "DotChainItem"_id: | 2019 | if (usage == ExpUsage::Closure) { |
1999 | case "ColonChainItem"_id: | 2020 | temp.push_back(s("(function()"sv) + nll(x)); |
2000 | if (_withVars.empty()) { | 2021 | pushScope(); |
2001 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | 2022 | } |
2002 | } else { | 2023 | auto partOne = x->new_ptr<ChainValue_t>(); |
2003 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | 2024 | for (auto it = chainList.begin();it != opIt;++it) { |
2004 | } | 2025 | partOne->items.push_back(*it); |
2026 | } | ||
2027 | BLOCK_START | ||
2028 | auto back = ast_cast<Callable_t>(partOne->items.back()); | ||
2029 | BREAK_IF(!back); | ||
2030 | auto selfName = ast_cast<SelfName_t>(back->item); | ||
2031 | BREAK_IF(!selfName); | ||
2032 | if (auto sname = ast_cast<self_name_t>(selfName->name)) { | ||
2033 | auto colonItem = x->new_ptr<ColonChainItem_t>(); | ||
2034 | colonItem->name.set(sname->name); | ||
2035 | partOne->items.pop_back(); | ||
2036 | partOne->items.push_back(toAst<Callable_t>("@"sv, Callable, x)); | ||
2037 | partOne->items.push_back(colonItem); | ||
2005 | break; | 2038 | break; |
2006 | } | 2039 | } |
2007 | auto end = --chainList.end(); | 2040 | if (auto cname = ast_cast<self_class_name_t>(selfName->name)) { |
2008 | for (auto it = chainList.begin(); it != end; ++it) { | 2041 | auto colonItem = x->new_ptr<ColonChainItem_t>(); |
2009 | baseChain->items.push_back(*it); | 2042 | colonItem->name.set(cname->name); |
2010 | } | 2043 | partOne->items.pop_back(); |
2011 | auto colonChainItem = static_cast<ColonChainItem_t*>(chainList.back()); | 2044 | partOne->items.push_back(toAst<Callable_t>("@@"sv, Callable, x)); |
2012 | auto funcName = toString(colonChainItem->name); | 2045 | partOne->items.push_back(colonItem); |
2013 | if (usage != ExpUsage::Return) pushScope(); | ||
2014 | auto baseVar = getUnusedName("_base_"sv); | ||
2015 | auto fnVar = getUnusedName("_fn_"sv); | ||
2016 | str_list temp; | ||
2017 | { | ||
2018 | auto value = x->new_ptr<Value_t>(); | ||
2019 | value->item.set(baseChain); | ||
2020 | auto exp = x->new_ptr<Exp_t>(); | ||
2021 | exp->value.set(value); | ||
2022 | auto assign = x->new_ptr<Assign_t>(); | ||
2023 | assign->values.push_back(exp); | ||
2024 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2025 | assignment->expList.set(toAst<ExpList_t>(baseVar, ExpList, x)); | ||
2026 | assignment->action.set(assign); | ||
2027 | transformAssignment(assignment, temp); | ||
2028 | } | ||
2029 | { | ||
2030 | auto assign = x->new_ptr<Assign_t>(); | ||
2031 | assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, Exp, x)); | ||
2032 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2033 | assignment->expList.set(toAst<ExpList_t>(fnVar, ExpList, x)); | ||
2034 | assignment->action.set(assign); | ||
2035 | transformAssignment(assignment, temp); | ||
2036 | } | ||
2037 | auto funLit = toAst<Exp_t>(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); | ||
2038 | switch (usage) { | ||
2039 | case ExpUsage::Return: | ||
2040 | transformExp(funLit, temp); | ||
2041 | _buf << temp.front(); | ||
2042 | _buf << *(++temp.begin()); | ||
2043 | _buf << indent() << "return " << temp.back() << nll(chainValue); | ||
2044 | break; | 2046 | break; |
2045 | case ExpUsage::Assignment: { | 2047 | } |
2048 | BLOCK_END | ||
2049 | auto objVar = singleVariableFrom(partOne); | ||
2050 | if (objVar.empty()) { | ||
2051 | objVar = getUnusedName("_obj_"sv); | ||
2052 | if (auto colonItem = ast_cast<ColonChainItem_t>(partOne->items.back())) { | ||
2053 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
2054 | chainValue->items.dup(partOne->items); | ||
2055 | chainValue->items.pop_back(); | ||
2056 | if (chainValue->items.empty()) { | ||
2057 | if (_withVars.empty()) { | ||
2058 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); | ||
2059 | } | ||
2060 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | ||
2061 | } | ||
2062 | auto newObj = singleVariableFrom(chainValue); | ||
2063 | if (!newObj.empty()) { | ||
2064 | objVar = newObj; | ||
2065 | } else { | ||
2066 | auto value = x->new_ptr<Value_t>(); | ||
2067 | value->item.set(chainValue); | ||
2068 | auto exp = x->new_ptr<Exp_t>(); | ||
2069 | exp->value.set(value); | ||
2070 | auto assign = x->new_ptr<Assign_t>(); | ||
2071 | assign->values.push_back(exp); | ||
2072 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
2073 | expListAssign->expList.set(toAst<ExpList_t>(objVar, ExpList, x)); | ||
2074 | expListAssign->action.set(assign); | ||
2075 | transformAssignment(expListAssign, temp); | ||
2076 | } | ||
2077 | auto dotItem = x->new_ptr<DotChainItem_t>(); | ||
2078 | auto name = colonItem->name.get(); | ||
2079 | if (auto keyword = ast_cast<LuaKeyword_t>(name)) { | ||
2080 | name = keyword->name.get(); | ||
2081 | } | ||
2082 | dotItem->name.set(name); | ||
2083 | partOne->items.clear(); | ||
2084 | partOne->items.push_back(toAst<Callable_t>(objVar, Callable, x)); | ||
2085 | partOne->items.push_back(dotItem); | ||
2086 | auto it = opIt; ++it; | ||
2087 | if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { | ||
2088 | |||
2089 | if (auto invoke = ast_cast<Invoke_t>(*it)) { | ||
2090 | invoke->args.push_front(toAst<Exp_t>(objVar, Exp, x)); | ||
2091 | } else { | ||
2092 | auto invokeArgs = static_cast<InvokeArgs_t*>(*it); | ||
2093 | invokeArgs->args.push_front(toAst<Exp_t>(objVar, Exp, x)); | ||
2094 | } | ||
2095 | } | ||
2096 | objVar = getUnusedName("_obj_"sv); | ||
2097 | } | ||
2098 | auto value = x->new_ptr<Value_t>(); | ||
2099 | value->item.set(partOne); | ||
2100 | auto exp = x->new_ptr<Exp_t>(); | ||
2101 | exp->value.set(value); | ||
2102 | auto assign = x->new_ptr<Assign_t>(); | ||
2103 | assign->values.push_back(exp); | ||
2104 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
2105 | expListAssign->expList.set(toAst<ExpList_t>(objVar, ExpList, x)); | ||
2106 | expListAssign->action.set(assign); | ||
2107 | transformAssignment(expListAssign, temp); | ||
2108 | } | ||
2109 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | ||
2110 | temp.push_back(clearBuf()); | ||
2111 | pushScope(); | ||
2112 | auto partTwo = x->new_ptr<ChainValue_t>(); | ||
2113 | partTwo->items.push_back(toAst<Callable_t>(objVar, Callable, x)); | ||
2114 | for (auto it = ++opIt;it != chainList.end();++it) { | ||
2115 | partTwo->items.push_back(*it); | ||
2116 | } | ||
2117 | switch (usage) { | ||
2118 | case ExpUsage::Common: | ||
2119 | transformChainValue(partTwo, temp, ExpUsage::Common); | ||
2120 | break; | ||
2121 | case ExpUsage::Assignment: { | ||
2122 | auto value = x->new_ptr<Value_t>(); | ||
2123 | value->item.set(partTwo); | ||
2124 | auto exp = x->new_ptr<Exp_t>(); | ||
2125 | exp->value.set(value); | ||
2126 | auto assign = x->new_ptr<Assign_t>(); | ||
2127 | assign->values.push_back(exp); | ||
2128 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2129 | assignment->expList.set(assignList); | ||
2130 | assignment->action.set(assign); | ||
2131 | transformAssignment(assignment, temp); | ||
2132 | break; | ||
2133 | } | ||
2134 | case ExpUsage::Return: | ||
2135 | case ExpUsage::Closure: { | ||
2136 | auto value = x->new_ptr<Value_t>(); | ||
2137 | value->item.set(partTwo); | ||
2138 | auto exp = x->new_ptr<Exp_t>(); | ||
2139 | exp->value.set(value); | ||
2140 | auto ret = x->new_ptr<Return_t>(); | ||
2141 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
2142 | expListLow->exprs.push_back(exp); | ||
2143 | ret->valueList.set(expListLow); | ||
2144 | transformReturn(ret, temp); | ||
2145 | break; | ||
2146 | } | ||
2147 | } | ||
2148 | popScope(); | ||
2149 | temp.push_back(indent() + s("end"sv) + nlr(x)); | ||
2150 | switch (usage) { | ||
2151 | case ExpUsage::Return: | ||
2152 | temp.push_back(indent() + s("return nil"sv) + nlr(x)); | ||
2153 | break; | ||
2154 | case ExpUsage::Closure: | ||
2155 | temp.push_back(indent() + s("return nil"sv) + nlr(x)); | ||
2156 | popScope(); | ||
2157 | temp.push_back(indent() + s("end)()"sv)); | ||
2158 | break; | ||
2159 | default: | ||
2160 | break; | ||
2161 | } | ||
2162 | out.push_back(join(temp)); | ||
2163 | return true; | ||
2164 | } | ||
2165 | return false; | ||
2166 | } | ||
2167 | |||
2168 | bool transformChainEndWithColonItem(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
2169 | if (ast_is<ColonChainItem_t>(chainList.back())) { | ||
2170 | auto x = chainList.front(); | ||
2171 | str_list temp; | ||
2172 | switch (usage) { | ||
2173 | case ExpUsage::Assignment: | ||
2174 | temp.push_back(indent() + s("do"sv) + nll(x)); | ||
2175 | pushScope(); | ||
2176 | break; | ||
2177 | case ExpUsage::Closure: | ||
2178 | temp.push_back(s("(function()"sv) + nll(x)); | ||
2179 | pushScope(); | ||
2180 | break; | ||
2181 | default: | ||
2182 | break; | ||
2183 | } | ||
2184 | auto baseChain = x->new_ptr<ChainValue_t>(); | ||
2185 | switch (chainList.front()->getId()) { | ||
2186 | case "DotChainItem"_id: | ||
2187 | case "ColonChainItem"_id: | ||
2188 | if (_withVars.empty()) { | ||
2189 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | ||
2190 | } else { | ||
2191 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | ||
2192 | } | ||
2193 | break; | ||
2194 | } | ||
2195 | auto end = --chainList.end(); | ||
2196 | for (auto it = chainList.begin(); it != end; ++it) { | ||
2197 | baseChain->items.push_back(*it); | ||
2198 | } | ||
2199 | auto colonChainItem = static_cast<ColonChainItem_t*>(chainList.back()); | ||
2200 | auto funcName = toString(colonChainItem->name); | ||
2201 | auto baseVar = getUnusedName("_base_"sv); | ||
2202 | auto fnVar = getUnusedName("_fn_"sv); | ||
2203 | { | ||
2204 | auto value = x->new_ptr<Value_t>(); | ||
2205 | value->item.set(baseChain); | ||
2206 | auto exp = x->new_ptr<Exp_t>(); | ||
2207 | exp->value.set(value); | ||
2046 | auto assign = x->new_ptr<Assign_t>(); | 2208 | auto assign = x->new_ptr<Assign_t>(); |
2047 | assign->values.push_back(funLit); | 2209 | assign->values.push_back(exp); |
2048 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 2210 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
2049 | assignment->expList.set(expList); | 2211 | assignment->expList.set(toAst<ExpList_t>(baseVar, ExpList, x)); |
2050 | assignment->action.set(assign); | 2212 | assignment->action.set(assign); |
2051 | transformAssignment(assignment, temp); | 2213 | transformAssignment(assignment, temp); |
2052 | _buf << indent(-1) << "do"sv << nll(chainValue); | ||
2053 | _buf << temp.front(); | ||
2054 | _buf << *(++temp.begin()); | ||
2055 | _buf << temp.back(); | ||
2056 | popScope(); | ||
2057 | _buf << indent() << "end"sv << nll(chainValue); | ||
2058 | break; | ||
2059 | } | 2214 | } |
2060 | case ExpUsage::Common: { | 2215 | { |
2061 | auto assign = x->new_ptr<Assign_t>(); | 2216 | auto assign = x->new_ptr<Assign_t>(); |
2062 | assign->values.push_back(funLit); | 2217 | assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, Exp, x)); |
2063 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 2218 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
2064 | assignment->expList.set(toAst<ExpList_t>("_"sv, ExpList, x)); | 2219 | assignment->expList.set(toAst<ExpList_t>(fnVar, ExpList, x)); |
2065 | assignment->action.set(assign); | 2220 | assignment->action.set(assign); |
2066 | transformAssignment(assignment, temp); | 2221 | transformAssignment(assignment, temp); |
2067 | _buf << indent(-1) << "do"sv << nll(chainValue); | ||
2068 | _buf << temp.front(); | ||
2069 | _buf << *(++temp.begin()); | ||
2070 | _buf << temp.back(); | ||
2071 | popScope(); | ||
2072 | _buf << indent() << "end"sv << nll(chainValue); | ||
2073 | break; | ||
2074 | } | 2222 | } |
2075 | default: break; | 2223 | auto funLit = toAst<Exp_t>(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); |
2224 | switch (usage) { | ||
2225 | case ExpUsage::Closure: | ||
2226 | case ExpUsage::Return: | ||
2227 | transformExp(funLit, temp); | ||
2228 | _buf << temp.front(); | ||
2229 | _buf << *(++temp.begin()); | ||
2230 | _buf << indent() << "return " << temp.back() << nll(x); | ||
2231 | break; | ||
2232 | case ExpUsage::Assignment: { | ||
2233 | auto assign = x->new_ptr<Assign_t>(); | ||
2234 | assign->values.push_back(funLit); | ||
2235 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2236 | assignment->expList.set(assignList); | ||
2237 | assignment->action.set(assign); | ||
2238 | transformAssignment(assignment, temp); | ||
2239 | break; | ||
2240 | } | ||
2241 | default: | ||
2242 | break; | ||
2243 | } | ||
2244 | switch (usage) { | ||
2245 | case ExpUsage::Assignment: | ||
2246 | popScope(); | ||
2247 | temp.push_back(indent() + s("end"sv) + nlr(x)); | ||
2248 | break; | ||
2249 | case ExpUsage::Closure: | ||
2250 | popScope(); | ||
2251 | temp.push_back(indent() + s("end)()"sv)); | ||
2252 | break; | ||
2253 | default: | ||
2254 | break; | ||
2255 | } | ||
2256 | out.push_back(join(temp)); | ||
2257 | return true; | ||
2076 | } | 2258 | } |
2077 | out.push_back(clearBuf()); | 2259 | return false; |
2078 | } | 2260 | } |
2079 | 2261 | ||
2080 | void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 2262 | void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
2081 | auto x = chainList.front(); | 2263 | auto x = chainList.front(); |
2082 | str_list temp; | 2264 | str_list temp; |
2083 | switch (chainList.front()->getId()) { | 2265 | switch (x->getId()) { |
2084 | case "DotChainItem"_id: | 2266 | case "DotChainItem"_id: |
2085 | case "ColonChainItem"_id: | 2267 | case "ColonChainItem"_id: |
2086 | if (_withVars.empty()) { | 2268 | if (_withVars.empty()) { |
2087 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | 2269 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); |
2088 | } else { | 2270 | } else { |
2089 | temp.push_back(_withVars.top()); | 2271 | temp.push_back(_withVars.top()); |
2090 | } | 2272 | } |
@@ -2101,8 +2283,20 @@ private: | |||
2101 | break; | 2283 | break; |
2102 | case "ColonChainItem"_id: { | 2284 | case "ColonChainItem"_id: { |
2103 | auto colonItem = static_cast<ColonChainItem_t*>(item); | 2285 | auto colonItem = static_cast<ColonChainItem_t*>(item); |
2104 | auto next = it; ++next; | 2286 | auto current = it; |
2287 | auto next = current; ++next; | ||
2105 | auto followItem = next != chainList.end() ? *next : nullptr; | 2288 | auto followItem = next != chainList.end() ? *next : nullptr; |
2289 | if (current != chainList.begin()) { | ||
2290 | --current; | ||
2291 | if (!ast_is<existential_op_t>(*current)) { | ||
2292 | ++current; | ||
2293 | } | ||
2294 | } | ||
2295 | if (ast_is<existential_op_t>(followItem)) { | ||
2296 | ++next; | ||
2297 | followItem = next != chainList.end() ? *next : nullptr; | ||
2298 | --next; | ||
2299 | } | ||
2106 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { | 2300 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { |
2107 | throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); | 2301 | throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); |
2108 | } | 2302 | } |
@@ -2117,7 +2311,7 @@ private: | |||
2117 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | 2311 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); |
2118 | break; | 2312 | break; |
2119 | } | 2313 | } |
2120 | for (auto i = chainList.begin(); i != it; ++i) { | 2314 | for (auto i = chainList.begin(); i != current; ++i) { |
2121 | chainValue->items.push_back(*i); | 2315 | chainValue->items.push_back(*i); |
2122 | } | 2316 | } |
2123 | auto value = x->new_ptr<Value_t>(); | 2317 | auto value = x->new_ptr<Value_t>(); |
@@ -2141,6 +2335,9 @@ private: | |||
2141 | auto name = toString(colonItem->name); | 2335 | auto name = toString(colonItem->name); |
2142 | auto chainValue = x->new_ptr<ChainValue_t>(); | 2336 | auto chainValue = x->new_ptr<ChainValue_t>(); |
2143 | chainValue->items.push_back(toAst<Callable_t>(callVar, Callable, x)); | 2337 | chainValue->items.push_back(toAst<Callable_t>(callVar, Callable, x)); |
2338 | if (ast_is<existential_op_t>(*current)) { | ||
2339 | chainValue->items.push_back(x->new_ptr<existential_op_t>()); | ||
2340 | } | ||
2144 | chainValue->items.push_back(toAst<Exp_t>(s("\""sv) + name + s("\""sv), Exp, x)); | 2341 | chainValue->items.push_back(toAst<Exp_t>(s("\""sv) + name + s("\""sv), Exp, x)); |
2145 | if (auto invoke = ast_cast<Invoke_t>(followItem)) { | 2342 | if (auto invoke = ast_cast<Invoke_t>(followItem)) { |
2146 | invoke->args.push_front(toAst<Exp_t>(callVar, Exp, x)); | 2343 | invoke->args.push_front(toAst<Exp_t>(callVar, Exp, x)); |
@@ -2148,8 +2345,7 @@ private: | |||
2148 | auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); | 2345 | auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); |
2149 | invokeArgs->args.push_front(toAst<Exp_t>(callVar, Exp, x)); | 2346 | invokeArgs->args.push_front(toAst<Exp_t>(callVar, Exp, x)); |
2150 | } | 2347 | } |
2151 | chainValue->items.push_back(followItem); | 2348 | for (auto i = next; i != chainList.end(); ++i) { |
2152 | for (auto i = ++next; i != chainList.end(); ++i) { | ||
2153 | chainValue->items.push_back(*i); | 2349 | chainValue->items.push_back(*i); |
2154 | } | 2350 | } |
2155 | auto value = x->new_ptr<Value_t>(); | 2351 | auto value = x->new_ptr<Value_t>(); |
@@ -2244,7 +2440,17 @@ private: | |||
2244 | } | 2440 | } |
2245 | 2441 | ||
2246 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Closure, ExpList_t* assignList = nullptr) { | 2442 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Closure, ExpList_t* assignList = nullptr) { |
2247 | transformChainList(chainValue->items.objects(), out, usage, assignList); | 2443 | const auto& chainList = chainValue->items.objects(); |
2444 | if (transformChainEndWithEOP(chainList, out, usage, assignList)) { | ||
2445 | return; | ||
2446 | } | ||
2447 | if (transformChainWithEOP(chainList, out, usage, assignList)) { | ||
2448 | return; | ||
2449 | } | ||
2450 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | ||
2451 | return; | ||
2452 | } | ||
2453 | transformChainList(chainList, out, usage, assignList); | ||
2248 | } | 2454 | } |
2249 | 2455 | ||
2250 | void transformAssignableChain(AssignableChain_t* chain, str_list& out) { | 2456 | void transformAssignableChain(AssignableChain_t* chain, str_list& out) { |
@@ -2957,7 +3163,7 @@ private: | |||
2957 | if (auto assignment = assignmentFrom(statement)) { | 3163 | if (auto assignment = assignmentFrom(statement)) { |
2958 | auto names = transformAssignDefs(assignment->expList.get()); | 3164 | auto names = transformAssignDefs(assignment->expList.get()); |
2959 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 3165 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
2960 | auto info = extractDestructureInfo(assignment); | 3166 | auto info = extractDestructureInfo(assignment, true); |
2961 | if (!info.first.empty()) { | 3167 | if (!info.first.empty()) { |
2962 | for (const auto& destruct : info.first) | 3168 | for (const auto& destruct : info.first) |
2963 | for (const auto& item : destruct.items) | 3169 | for (const auto& item : destruct.items) |
@@ -3342,7 +3548,7 @@ private: | |||
3342 | if (!names.empty()) { | 3548 | if (!names.empty()) { |
3343 | return traversal::Stop; | 3549 | return traversal::Stop; |
3344 | } | 3550 | } |
3345 | auto info = extractDestructureInfo(assignment); | 3551 | auto info = extractDestructureInfo(assignment, true); |
3346 | if (!info.first.empty()) { | 3552 | if (!info.first.empty()) { |
3347 | for (const auto& destruct : info.first) | 3553 | for (const auto& destruct : info.first) |
3348 | for (const auto& item : destruct.items) | 3554 | for (const auto& item : destruct.items) |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 1005463..7cc4129 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -289,9 +289,9 @@ extern rule Value; | |||
289 | rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; | 289 | rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; |
290 | rule Exp = Value >> *exp_op_value; | 290 | rule Exp = Value >> *exp_op_value; |
291 | 291 | ||
292 | extern rule Chain, Callable, InvokeArgs; | 292 | extern rule Chain, Callable, InvokeArgs, existential_op; |
293 | 293 | ||
294 | rule ChainValue = Seperator >> (Chain | Callable) >> -InvokeArgs; | 294 | rule ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; |
295 | 295 | ||
296 | extern rule KeyValue, String, SimpleValue; | 296 | extern rule KeyValue, String, SimpleValue; |
297 | 297 | ||
@@ -345,9 +345,10 @@ rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym( | |||
345 | 345 | ||
346 | extern rule ChainItems, DotChainItem, ColonChain; | 346 | extern rule ChainItems, DotChainItem, ColonChain; |
347 | 347 | ||
348 | rule chain_call = (Callable | String) >> ChainItems; | 348 | rule existential_op = expr('?'); |
349 | rule chain_call = (Callable | String) >> -existential_op >> ChainItems; | ||
349 | rule chain_item = and_(set(".\\")) >> ChainItems; | 350 | rule chain_item = and_(set(".\\")) >> ChainItems; |
350 | rule chain_dot_chain = DotChainItem >> -ChainItems; | 351 | rule chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; |
351 | 352 | ||
352 | rule Chain = chain_call | chain_item | | 353 | rule Chain = chain_call | chain_item | |
353 | Space >> (chain_dot_chain | ColonChain); | 354 | Space >> (chain_dot_chain | ColonChain); |
@@ -362,11 +363,11 @@ rule ChainItems = chain_with_colon | ColonChain; | |||
362 | extern rule Invoke, Slice; | 363 | extern rule Invoke, Slice; |
363 | 364 | ||
364 | rule Index = symx('[') >> Exp >> sym(']'); | 365 | rule Index = symx('[') >> Exp >> sym(']'); |
365 | rule ChainItem = Invoke | DotChainItem | Slice | Index; | 366 | rule ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; |
366 | rule DotChainItem = symx('.') >> Name; | 367 | rule DotChainItem = symx('.') >> Name; |
367 | rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); | 368 | rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); |
368 | rule invoke_chain = Invoke >> -ChainItems; | 369 | rule invoke_chain = Invoke >> -existential_op >> -ChainItems; |
369 | rule ColonChain = ColonChainItem >> -invoke_chain; | 370 | rule ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; |
370 | 371 | ||
371 | rule default_value = true_(); | 372 | rule default_value = true_(); |
372 | rule Slice = | 373 | rule Slice = |
diff --git a/src/moonc.cpp b/src/moonc.cpp index 02d5275..4498bee 100644 --- a/src/moonc.cpp +++ b/src/moonc.cpp | |||
@@ -22,14 +22,13 @@ int main(int narg, const char** args) { | |||
22 | " -p Write output to standard out\n" | 22 | " -p Write output to standard out\n" |
23 | " -b Dump compile time (doesn't write output)\n" | 23 | " -b Dump compile time (doesn't write output)\n" |
24 | " -l Write line numbers from source codes\n" | 24 | " -l Write line numbers from source codes\n" |
25 | " -a Allow expression list not in the end of body block\n" | ||
26 | " -s Use space over tab\n" | ||
27 | " -v Print version\n"; | 25 | " -v Print version\n"; |
28 | if (narg == 0) { | 26 | if (narg == 0) { |
29 | std::cout << help; | 27 | std::cout << help; |
30 | return 0; | 28 | return 0; |
31 | } | 29 | } |
32 | MoonP::MoonConfig config; | 30 | MoonP::MoonConfig config; |
31 | config.reserveLineNumber = false; | ||
33 | bool writeToFile = true; | 32 | bool writeToFile = true; |
34 | bool dumpCompileTime = false; | 33 | bool dumpCompileTime = false; |
35 | std::string targetPath; | 34 | std::string targetPath; |
@@ -37,18 +36,9 @@ int main(int narg, const char** args) { | |||
37 | std::list<std::string> files; | 36 | std::list<std::string> files; |
38 | for (int i = 1; i < narg; ++i) { | 37 | for (int i = 1; i < narg; ++i) { |
39 | switch (hash(args[i])) { | 38 | switch (hash(args[i])) { |
40 | case "-a"_id: | ||
41 | config.allowExprNotInTheEndOfBody = true; | ||
42 | break; | ||
43 | case "-s"_id: | ||
44 | config.spaceOverTab = true; | ||
45 | break; | ||
46 | case "-l"_id: | 39 | case "-l"_id: |
47 | config.reserveLineNumber = true; | 40 | config.reserveLineNumber = true; |
48 | break; | 41 | break; |
49 | case "-r"_id: | ||
50 | config.reuseVariable = true; | ||
51 | break; | ||
52 | case "-p"_id: | 42 | case "-p"_id: |
53 | writeToFile = false; | 43 | writeToFile = false; |
54 | break; | 44 | break; |