1use error::ErrorTuple;
2use lua::Lua;
3use value::Value;
4
5mod chunk;
6mod code;
7pub mod compiler;
8mod error;
9mod function;
10mod lexer;
11pub mod lua;
12pub mod prelude;
13pub mod standard;
14pub mod table;
15mod token;
16mod userdata;
17pub mod value;
18
19use wasm_bindgen::prelude::*;
20
21fn simple(source: &str) -> Value {
22 let mut vm = Lua::new();
23 vm.load_standard_library();
24 match vm.run(source) {
25 Ok(v) => v,
26 Err(e) => Value::String(Box::new(e[0].to_string())),
27 }
28
29 }
35
36fn complex(source: &str) -> Result<Value, ErrorTuple> {
37 let mut vm = Lua::new();
38 vm.load_standard_library();
39 match vm.run(source) {
40 Ok(v) => Ok(v),
41 Err(e) => Err(e.get(0).unwrap().clone()),
42 }
43}
44
45#[wasm_bindgen]
46extern "C" {
47 pub fn jprintln(s: &str);
48}
49
50#[wasm_bindgen]
51pub fn run(source: &str) -> String {
52 let mut vm = Lua::new();
53 vm.load_standard_library();
54 match vm.run(source) {
55 Ok(v) => v.to_string(),
56 Err(e) => e[0].to_string(),
57 }
58}
59
60macro_rules! valeq {
61 ($source:literal, $val:expr) => {
62 assert_eq!(simple($source), $val);
63 };
64}
65
66macro_rules! fails {
67 ($source:literal, $val:expr) => {{
68 match complex($source) {
69 Ok(_) => panic!("Expected error"),
70 Err(e) => assert_eq!(e.code, $val),
71 }
72 }};
73}
74
75macro_rules! vstr {
76 ($source:literal) => {
77 Value::String(Box::new($source.to_string()))
78 };
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::{
84 chunk::Chunk,
85 code::{self, OpCode},
86 complex,
87 error::SiltError,
88 function::FunctionObject,
89 lua::Lua,
90 prelude::ErrorTypes,
91 simple,
92 token::{Operator, Token},
93 value::Value,
94 };
95 use std::{mem::size_of, println, rc::Rc};
96
97 #[test]
98 fn test_32bits() {
99 println!("size of i32: {}", size_of::<i32>());
100 println!("size of i64: {}", size_of::<i64>());
101 println!("size of f32: {}", size_of::<f32>());
102 println!("size of f64: {}", size_of::<f64>());
103 println!("size of bool: {}", size_of::<bool>());
104 println!("size of char: {}", size_of::<char>());
105 println!("size of usize: {}", size_of::<usize>());
106 println!("size of u8: {}", size_of::<u8>());
107 println!("size of &str: {}", size_of::<&str>());
108 println!("size of String: {}", size_of::<String>());
109 println!("size of Box<str>: {}", size_of::<Box<str>>());
110 println!("size of boxed<Strinv> {}", size_of::<Box<String>>());
111 println!("size of Operator: {}", size_of::<crate::token::Operator>());
112 println!("size of Tester: {}", size_of::<crate::code::Tester>());
113 println!("size of Flag: {}", size_of::<crate::token::Flag>());
114 println!("size of token: {}", size_of::<Token>());
115
116 println!("size of token: {}", size_of::<Token>());
117 println!(
118 "size of silt_error: {}",
119 size_of::<crate::error::SiltError>()
120 );
121 println!(
122 "size of error_types: {}",
123 size_of::<crate::error::ErrorTypes>()
124 );
125
126 println!("size of value: {}", size_of::<crate::value::Value>());
127 println!("size of OpCode: {}", size_of::<crate::code::OpCode>());
128
129 assert!(size_of::<Token>() == 24);
130 assert!(size_of::<crate::code::OpCode>() == 4);
131 }
132
133 #[test]
134 fn speed() {
135 let source_in = r#"
136 start=clock()
137 i=1
138 a="a"
139 while i < 100000 do
140 i = i +1
141 a = a .. "1"
142 end
143 elapsed=clock()-start
144 print "done "
145 print ("elapsed: "..elapsed)
146 return {elapsed,i}
147 "#;
148 let tuple = if let crate::value::Value::Table(t) = simple(source_in) {
149 let tt = t.borrow();
150 (
151 if let Some(&Value::Number(n)) = tt.getn(1) {
152 n
153 } else {
154 999999.
155 },
156 if let Some(&Value::Integer(n)) = tt.getn(2) {
157 println!("{} iterations", n);
158 n
159 } else {
160 0
161 },
162 )
163 } else {
164 panic!("not a table")
165 };
166
167 assert!(tuple.1 == 100_000);
169 }
170
171 #[test]
190 fn fib() {
191 let source_in = r#"
192 start=clock()
193 function fib(n)
194 if n <= 1 then
195 return n
196 else
197 return fib(n-1) + fib(n-2)
198 end
199 end
200
201 for i = 1, 25 do
202 print(i..":"..fib(i))
203 end
204 elapsed=clock()-start
205 return elapsed
206 "#;
207
208 let n = if let crate::value::Value::Number(n) = simple(source_in) {
209 println!("{} seconds", n);
210 n
211 } else {
212 999999.
213 };
214 println!("{} seconds", n);
215 }
217 #[test]
218 fn chunk_validity() {
219 let mut c = Chunk::new();
220 c.write_value(Value::Number(1.2), (1, 1));
221 c.write_value(Value::Number(3.4), (1, 2));
222 c.write_code(OpCode::ADD, (1, 3));
223 c.write_value(Value::Number(9.2), (1, 4));
224 c.write_code(OpCode::DIVIDE, (1, 5));
225 c.write_code(OpCode::NEGATE, (1, 1));
226 c.write_code(OpCode::RETURN, (1, 3));
227 c.print_chunk(None);
228 println!("-----------------");
229 let blank = FunctionObject::new(None, false);
230 let mut tester = FunctionObject::new(None, false);
231 tester.set_chunk(c);
232 let mut vm = Lua::new();
233 match vm.execute(Rc::new(tester)) {
234 Ok(v) => {
235 assert_eq!(v, Value::Number(-0.5));
236 }
237 Err(e) => {
238 panic!("Test should not fail with error: {}", e)
239 }
240 }
241 }
242
243 #[test]
244 fn compliance() {
245 valeq!("return 1+2", Value::Integer(3));
246 valeq!("return '1'..'2'", vstr!("12"));
247
248 valeq!(
249 r#"
250 local a= 1+2
251 return a
252 "#,
253 Value::Integer(3)
254 );
255 valeq!(
256 r#"
257 local a= '1'..'2'
258 return a
259 "#,
260 vstr!("12")
261 );
262 valeq!(
263 r#"
264 local a= 'a'
265 a='b'
266 local b='c'
267 b=a..b
268 return b
269 "#,
270 vstr!("bc")
271 );
272 }
273
274 #[test]
275 fn string_infererence() {
276 valeq!("return '1'+2", Value::Integer(3));
277 fails!(
278 "return 'a1'+2",
279 SiltError::ExpOpValueWithValue(ErrorTypes::String, Operator::Add, ErrorTypes::Integer)
280 );
281 }
282
283 #[test]
284 fn scope() {
285 valeq!(
286 r#"
287 -- for loop closures should capture the loop variable at that point in time and not the final value of the loop variable
288 a = {}
289 do
290 for i = 1, 3 do
291 local function t()
292 return i
293 end
294 a[i] = t
295 end
296
297 return a[1]() + a[2]() + a[3]() -- 1+2+3 = 6
298 end
299 "#,
300 Value::Integer(6)
301 );
302 valeq!(
303 r#"
304 -- Same but test in global scope
305 a = {}
306 for i = 1, 3 do
307 local function t()
308 return i
309 end
310 a[i] = t
311 end
312
313 return a[1]() + a[2]() + a[3]() -- 1+2+3 = 6
314 "#,
315 Value::Integer(6)
316 );
317 }
318
319 #[test]
320 fn closures() {
321 valeq!(
322 r#"
323 do
324 local a = 1
325 local b = 2
326 local function f1()
327 local c = 3
328 local function f2()
329 local d = 4
330 c = c + d -- 7, 11
331 return a + b + c + d -- 1+2+7+4= 14, 1+2+11+4 = 18
332 end
333 return f2
334 end
335 local e = 1000
336 local x = f1()
337 return x() + x() -- 14+18 = 32
338 end
339 "#,
340 Value::Integer(32)
341 );
342 }
343
344 #[test]
345 fn closures2() {
346 valeq!(
347 r#"
348 do
349 local a = 1
350 function f1()
351 return a
352 end
353
354 local b = f1()
355 a = 3
356 b = b + f1()
357 return b --4
358 end
359 "#,
360 Value::Integer(4)
361 );
362 valeq!(
363 r#"
364 do
365 function outer()
366 local y = 0
367 local x = 2
368 local function middle()
369 local function inner()
370 return x
371 end
372 y = y + 1
373 return inner
374 end
375
376 y = y + 1
377 x = x + y
378 return middle
379 end
380
381 a = outer()
382 b = a()
383 return b()
384 end
385 "#,
386 Value::Integer(3)
387 );
388 }
389}