Browse Source

implicit arguments for user defined functions

Inderjit Gill 1 month ago
parent
commit
9fb622adc1
2 changed files with 111 additions and 6 deletions
  1. 74
    6
      core/src/compiler.rs
  2. 37
    0
      core/src/vm.rs

+ 74
- 6
core/src/compiler.rs View File

@@ -31,6 +31,8 @@ use crate::vm::{Var, MEMORY_LOCAL_SIZE};
31 31
 
32 32
 use log::error;
33 33
 
34
+const NONSENSE: i32 = 666;
35
+
34 36
 pub fn compile_preamble() -> Result<Program> {
35 37
     let mut compilation = Compilation::new();
36 38
     let compiler = Compiler::new();
@@ -2245,30 +2247,34 @@ impl Compiler {
2245 2247
         // prepare the MEM_SEG_ARGUMENT with default values
2246 2248
 
2247 2249
         // for the function address
2248
-        compilation.emit(Opcode::LOAD, Mem::Constant, 666)?;
2250
+        compilation.emit(Opcode::LOAD, Mem::Constant, NONSENSE)?;
2249 2251
         // for the num args
2250
-        compilation.emit(Opcode::LOAD, Mem::Constant, 667)?;
2252
+        compilation.emit(Opcode::LOAD, Mem::Constant, NONSENSE)?;
2251 2253
 
2252 2254
         compilation.emit(Opcode::CALL, fn_info_index, fn_info_index)?;
2253 2255
 
2254 2256
         // overwrite the default arguments with the actual arguments given by the fn invocation
2255 2257
         let mut arg_vals = &children[..];
2256
-        while arg_vals.len() > 1 {
2258
+        while arg_vals.len() > 0 {
2257 2259
             let arg = &arg_vals[0];
2258 2260
             if let Node::Label(_, iname, _) = arg {
2259 2261
                 let val = &arg_vals[1];
2260 2262
                 self.compile(compilation, val)?;
2261 2263
                 compilation.emit(Opcode::PLACEHOLDER_STORE, fn_info_index, *iname)?;
2264
+                arg_vals = &arg_vals[2..];
2265
+            } else if let Node::Name(_, iname, _) = arg {
2266
+                let val = &arg_vals[0];
2267
+                self.compile(compilation, val)?;
2268
+                compilation.emit(Opcode::PLACEHOLDER_STORE, fn_info_index, *iname)?;
2269
+                arg_vals = &arg_vals[1..];
2262 2270
             } else {
2263 2271
                 error!("compile_fn_invocation");
2264 2272
                 return Err(Error::Compiler);
2265 2273
             }
2266
-
2267
-            arg_vals = &arg_vals[2..];
2268 2274
         }
2269 2275
 
2270 2276
         // call the body of the function
2271
-        compilation.emit(Opcode::LOAD, Mem::Constant, 668)?;
2277
+        compilation.emit(Opcode::LOAD, Mem::Constant, NONSENSE)?;
2272 2278
         compilation.emit(Opcode::CALL_0, fn_info_index, fn_info_index)?;
2273 2279
 
2274 2280
         Ok(())
@@ -3156,4 +3162,66 @@ mod tests {
3156 3162
             expected_bytecode
3157 3163
         );
3158 3164
     }
3165
+
3166
+    #[test]
3167
+    fn test_fn_invocation_2() {
3168
+        let expected_bytecode = vec![
3169
+            jump(14),
3170
+            load_const_name(224),
3171
+            store_arg(0),
3172
+            load_const_f32(99.0),
3173
+            store_arg(1),
3174
+            load_const_name(225),
3175
+            store_arg(2),
3176
+            load_const_f32(88.0),
3177
+            store_arg(3),
3178
+            ret_0(),
3179
+            load_arg(1),
3180
+            load_arg(3),
3181
+            add(),
3182
+            ret(),
3183
+            load_const_f32(1.0),
3184
+            store_global(15),
3185
+            load_const_f32(2.0),
3186
+            store_global(16),
3187
+            load_const_i32(1),
3188
+            load_const_i32(2),
3189
+            call(),
3190
+            load_global_i32(15),
3191
+            store_arg(1),
3192
+            load_global_i32(16),
3193
+            store_arg(3),
3194
+            load_const_i32(10),
3195
+            call_0(),
3196
+            stop(),
3197
+        ];
3198
+
3199
+        assert_eq!(
3200
+            compile(
3201
+                "(define x 1 y 2)
3202
+                 (fn (adder a: 99 b: 88) (+ a b))
3203
+                 (adder a: x b: y)"
3204
+            ),
3205
+            expected_bytecode
3206
+        );
3207
+
3208
+        assert_eq!(
3209
+            compile(
3210
+                "(define a 1 b 2)
3211
+                 (fn (adder a: 99 b: 88) (+ a b))
3212
+                 (adder a: a b: b)"
3213
+            ),
3214
+            expected_bytecode
3215
+        );
3216
+
3217
+        assert_eq!(
3218
+            compile(
3219
+                "(define a 1 b 2)
3220
+                 (fn (adder a: 99 b: 88) (+ a b))
3221
+                 (adder a b)"
3222
+            ),
3223
+            expected_bytecode
3224
+        );
3225
+    }
3226
+
3159 3227
 }

+ 37
- 0
core/src/vm.rs View File

@@ -1836,6 +1836,43 @@ pub mod tests {
1836 1836
     }
1837 1837
 
1838 1838
     #[test]
1839
+    fn test_vm_implied_args() {
1840
+        // explicit argument syntax
1841
+        is_float(
1842
+            "(define x 1 y 2)
1843
+             (fn (adder a: 99 b: 88) (+ a b))
1844
+             (adder a: x b: y)",
1845
+            3.0,
1846
+        );
1847
+
1848
+        // explicit argument syntax, same names
1849
+        is_float(
1850
+            "(define a 1 b 2)
1851
+             (fn (adder a: 99 b: 88) (+ a b))
1852
+             (adder a: a b: b)",
1853
+            3.0,
1854
+        );
1855
+
1856
+        // implied argument syntax
1857
+        is_float(
1858
+            "(define a 1 b 2)
1859
+             (fn (adder a: 99 b: 88) (+ a b))
1860
+             (adder a b)",
1861
+            3.0,
1862
+        );
1863
+
1864
+        // default argument value plus the value of b is set to the global a
1865
+        // if implied argument syntax is going to mess up, it will mess up here
1866
+        //
1867
+        is_float(
1868
+            "(define a 5 b 10)
1869
+             (fn (adder a: 99 b: 88) (+ a b))
1870
+             (adder b: a)",
1871
+            104.0,
1872
+        );
1873
+    }
1874
+
1875
+    #[test]
1839 1876
     fn test_vm_function_address() {
1840 1877
         is_float(
1841 1878
             "(fn (k a: 5) (+ a a))

Loading…
Cancel
Save