Browse Source

dot syntax works for user defined functions

Inderjit Gill 1 month ago
parent
commit
eb4de8f989
4 changed files with 188 additions and 12 deletions
  1. 129
    12
      core/src/compiler.rs
  2. 11
    0
      core/src/lexer.rs
  3. 47
    0
      core/src/parser.rs
  4. 1
    0
      core/src/unparser.rs

+ 129
- 12
core/src/compiler.rs View File

@@ -212,6 +212,12 @@ fn assign_genes_to_nodes(node: &mut Node, genotype: &mut Genotype) -> Result<()>
212 212
                 genotype.current_gene_index += 1;
213 213
             }
214 214
         }
215
+        Node::FromName(_, _, meta) => {
216
+            if let Some(ref mut node_meta) = meta {
217
+                node_meta.gene = Some(genotype.genes[genotype.current_gene_index].clone());
218
+                genotype.current_gene_index += 1;
219
+            }
220
+        }
215 221
         Node::Name(_, _, meta) => {
216 222
             if let Some(ref mut node_meta) = meta {
217 223
                 node_meta.gene = Some(genotype.genes[genotype.current_gene_index].clone());
@@ -1211,6 +1217,22 @@ impl Compiler {
1211 1217
                     Err(Error::Compiler)
1212 1218
                 };
1213 1219
             }
1220
+            Node::FromName(text, _, _) => {
1221
+                let iname = self.get_iname(ast)?;
1222
+
1223
+                return if self.compile_user_defined_name(compilation, iname)? {
1224
+                    Ok(())
1225
+                } else if let Some(kw) = self.name_to_keyword.get(&iname) {
1226
+                    compilation.emit(Opcode::LOAD, Mem::Constant, *kw)?;
1227
+                    Ok(())
1228
+                } else if let Some(native) = self.name_to_native.get(&iname) {
1229
+                    compilation.emit(Opcode::NATIVE, *native, 0)?;
1230
+                    Ok(())
1231
+                } else {
1232
+                    error!("compile: can't find user defined name or keyword: {}", text);
1233
+                    Err(Error::Compiler)
1234
+                };
1235
+            }
1214 1236
             _ => {
1215 1237
                 error!("compile ast: {:?}", ast);
1216 1238
                 return Err(Error::Compiler);
@@ -1232,17 +1254,35 @@ impl Compiler {
1232 1254
                 let kids = only_semantic_nodes(kids);
1233 1255
                 self.compile_list(compilation, &kids[..])?
1234 1256
             }
1257
+            Node::FromName(_, _, _) => {
1258
+                // syntax sugar for the 'from' parameter
1259
+                // e.g. (some-vec.vector/length)
1260
+                // is equivalent to (vector/length from: some-vec)
1261
+
1262
+                if children.len() == 1 || !children[1].is_name() {
1263
+                    error!("Node::FromName should always be followed by a Node::Name");
1264
+                    return Err(Error::Compiler);
1265
+                }
1266
+
1267
+                if let Some(fn_info_index) = compilation.get_fn_info_index(&children[1]) {
1268
+
1269
+                    self.compile_fn_invocation_prologue(compilation, fn_info_index)?;
1270
+                    self.compile_fn_invocation_implicit_from(compilation, fn_info_index, &children[0])?;
1271
+                    self.compile_fn_invocation_args(compilation, &children[2..], fn_info_index)?;
1272
+                    self.compile_fn_invocation_epilogue(compilation, fn_info_index)?;
1273
+
1274
+                }
1275
+            }
1235 1276
             Node::Name(_, _, _) => {
1236 1277
                 let iname = self.get_iname(&children[0])?;
1237 1278
 
1238 1279
                 if let Some(fn_info_index) = compilation.get_fn_info_index(&children[0]) {
1239 1280
                     // todo: get_fn_info_index is re-checking that this is a Node::Name
1240
-                    self.compile_fn_invocation(compilation, &children[1..], fn_info_index)?;
1241
-                    return Ok(());
1242
-                }
1243 1281
 
1244
-                if self.compile_user_defined_name(compilation, iname)? {
1245
-                    return Ok(());
1282
+                    self.compile_fn_invocation_prologue(compilation, fn_info_index)?;
1283
+                    self.compile_fn_invocation_args(compilation, &children[1..], fn_info_index)?;
1284
+                    self.compile_fn_invocation_epilogue(compilation, fn_info_index)?;
1285
+
1246 1286
                 } else if let Some(kw) = self.name_to_keyword.get(&iname) {
1247 1287
                     match *kw {
1248 1288
                         Keyword::Define => {
@@ -2231,13 +2271,10 @@ impl Compiler {
2231 2271
         Ok(())
2232 2272
     }
2233 2273
 
2234
-    // if (adder a: 10 b: 20) then children == a: 10 b: 20
2235
-    fn compile_fn_invocation(
2236
-        &self,
2237
-        compilation: &mut Compilation,
2238
-        children: &[&Node],
2239
-        fn_info_index: usize,
2240
-    ) -> Result<()> {
2274
+
2275
+    fn compile_fn_invocation_prologue(&self,
2276
+                                      compilation: &mut Compilation,
2277
+                                      fn_info_index: usize) -> Result<()> {
2241 2278
         // NOTE: CALL and CALL_0 get their function offsets and num args from the
2242 2279
         // stack so add some placeholder LOAD CONST opcodes and fill the CALL, CALL_0
2243 2280
         // with fn_info indexes that can later be used to fill in the LOAD CONST
@@ -2253,6 +2290,29 @@ impl Compiler {
2253 2290
 
2254 2291
         compilation.emit(Opcode::CALL, fn_info_index, fn_info_index)?;
2255 2292
 
2293
+        Ok(())
2294
+    }
2295
+
2296
+    fn compile_fn_invocation_implicit_from(
2297
+        &self,
2298
+        compilation: &mut Compilation,
2299
+        fn_info_index: usize,
2300
+        from_name: &Node,
2301
+    ) -> Result<()> {
2302
+
2303
+        self.compile(compilation, from_name)?;
2304
+        let from_iname = Iname::from(Keyword::From);
2305
+        compilation.emit(Opcode::PLACEHOLDER_STORE, fn_info_index, from_iname)?;
2306
+
2307
+        Ok(())
2308
+    }
2309
+
2310
+    fn compile_fn_invocation_args(
2311
+        &self,
2312
+        compilation: &mut Compilation,
2313
+        children: &[&Node],
2314
+        fn_info_index: usize,
2315
+    ) -> Result<()> {
2256 2316
         // overwrite the default arguments with the actual arguments given by the fn invocation
2257 2317
         let mut arg_vals = &children[..];
2258 2318
         while arg_vals.len() > 0 {
@@ -2272,7 +2332,12 @@ impl Compiler {
2272 2332
                 return Err(Error::Compiler);
2273 2333
             }
2274 2334
         }
2335
+        Ok(())
2336
+    }
2275 2337
 
2338
+    fn compile_fn_invocation_epilogue(&self,
2339
+                                      compilation: &mut Compilation,
2340
+                                      fn_info_index: usize) -> Result<()> {
2276 2341
         // call the body of the function
2277 2342
         compilation.emit(Opcode::LOAD, Mem::Constant, NONSENSE)?;
2278 2343
         compilation.emit(Opcode::CALL_0, fn_info_index, fn_info_index)?;
@@ -3224,4 +3289,56 @@ mod tests {
3224 3289
         );
3225 3290
     }
3226 3291
 
3292
+    #[test]
3293
+    fn test_fromname_fn_invocation() {
3294
+        let expected_bytecode = vec![
3295
+            jump(14),
3296
+            load_const_name(259),
3297
+            store_arg(0),
3298
+            load_const_f32(99.0),
3299
+            store_arg(1),
3300
+            load_const_name(246),
3301
+            store_arg(2),
3302
+            load_const_f32(88.0),
3303
+            store_arg(3),
3304
+            ret_0(),
3305
+            load_arg(1),
3306
+            load_arg(3),
3307
+            add(),
3308
+            ret(),
3309
+            load_const_f32(33.0),
3310
+            store_global(15),
3311
+            load_const_i32(1),
3312
+            load_const_i32(2),
3313
+            call(),
3314
+            load_global_i32(15),
3315
+            store_arg(1),
3316
+            load_const_f32(10.0),
3317
+            store_arg(3),
3318
+            load_const_i32(10),
3319
+            call_0(),
3320
+            stop(),
3321
+        ];
3322
+
3323
+        // traditional syntax
3324
+        assert_eq!(
3325
+            compile(
3326
+                "(define x 33)
3327
+                 (fn (increase from: 99 by: 88) (+ from by))
3328
+                 (increase from: x by: 10)"
3329
+            ),
3330
+            expected_bytecode
3331
+        );
3332
+
3333
+        // fromname syntax
3334
+        assert_eq!(
3335
+            compile(
3336
+                "(define x 33)
3337
+                 (fn (increase from: 99 by: 88) (+ from by))
3338
+                 (x.increase by: 10)"
3339
+            ),
3340
+            expected_bytecode
3341
+        );
3342
+    }
3343
+
3227 3344
 }

+ 11
- 0
core/src/lexer.rs View File

@@ -25,6 +25,7 @@ pub enum Token<'a> {
25 25
     Comment(&'a str),
26 26
     CurlyBracketEnd,
27 27
     CurlyBracketStart,
28
+    Dot,
28 29
     String(&'a str),
29 30
     Name(&'a str),
30 31
     Number(&'a str),
@@ -74,6 +75,7 @@ impl<'a> Lexer<'a> {
74 75
                 ']' => Ok((Token::SquareBracketEnd, 1)),
75 76
                 '{' => Ok((Token::CurlyBracketStart, 1)),
76 77
                 '}' => Ok((Token::CurlyBracketEnd, 1)),
78
+                '.' => Ok((Token::Dot, 1)),
77 79
                 ':' => Ok((Token::Colon, 1)),
78 80
                 '\'' => Ok((Token::Quote, 1)),
79 81
                 '`' => Ok((Token::BackQuote, 1)),
@@ -249,6 +251,15 @@ mod tests {
249 251
             ]
250 252
         );
251 253
 
254
+        assert_eq!(
255
+            tokenize("some-vector.vec/length").unwrap(),
256
+            [
257
+                Token::Name("some-vector"),
258
+                Token::Dot,
259
+                Token::Name("vec/length")
260
+            ]
261
+        );
262
+
252 263
         assert_eq!(tokenize("5").unwrap(), [Token::Number("5")]);
253 264
         assert_eq!(tokenize("-3").unwrap(), [Token::Number("-3")]);
254 265
         assert_eq!(tokenize("3.14").unwrap(), [Token::Number("3.14")]);

+ 47
- 0
core/src/parser.rs View File

@@ -51,6 +51,7 @@ pub enum Node {
51 51
     List(Vec<Node>, Option<NodeMeta>),
52 52
     Vector(Vec<Node>, Option<NodeMeta>),
53 53
     Float(f32, String, Option<NodeMeta>),
54
+    FromName(String, Iname, Option<NodeMeta>),  // text, iname, meta
54 55
     Name(String, Iname, Option<NodeMeta>),  // text, iname, meta
55 56
     Label(String, Iname, Option<NodeMeta>), // text, iname, meta
56 57
     String(String, Iname, Option<NodeMeta>),
@@ -107,6 +108,23 @@ impl Node {
107 108
                     return Ok(*iname);
108 109
                 }
109 110
             }
111
+            Node::FromName(_text, iname, meta) => {
112
+                if use_genes && meta.is_some() {
113
+                    if let Some(meta) = meta {
114
+                        if let Some(gene) = &meta.gene {
115
+                            match gene {
116
+                                Gene::Name(i) => return Ok(*i),
117
+                                _ => {
118
+                                    error!("Node::get_iname incompatible gene for FromName");
119
+                                    return Err(Error::Parser);
120
+                                }
121
+                            }
122
+                        }
123
+                    }
124
+                } else {
125
+                    return Ok(*iname);
126
+                }
127
+            }
110 128
             Node::String(_text, iname, meta) => {
111 129
                 if use_genes && meta.is_some() {
112 130
                     if let Some(meta) = meta {
@@ -210,11 +228,19 @@ impl Node {
210 228
         Err(Error::Parser)
211 229
     }
212 230
 
231
+    pub fn is_name(&self) -> bool {
232
+        match self {
233
+            Node::Name(_, _, _) => true,
234
+            _ => false
235
+        }
236
+    }
237
+
213 238
     pub fn is_alterable(&self) -> bool {
214 239
         match self {
215 240
             Node::List(_, meta)
216 241
             | Node::Vector(_, meta)
217 242
             | Node::Float(_, _, meta)
243
+            | Node::FromName(_, _, meta)
218 244
             | Node::Name(_, _, meta)
219 245
             | Node::Label(_, _, meta)
220 246
             | Node::String(_, _, meta)
@@ -228,6 +254,7 @@ impl Node {
228 254
             Node::List(_, meta)
229 255
             | Node::Vector(_, meta)
230 256
             | Node::Float(_, _, meta)
257
+            | Node::FromName(_, _, meta)
231 258
             | Node::Name(_, _, meta)
232 259
             | Node::Label(_, _, meta)
233 260
             | Node::String(_, _, meta)
@@ -498,6 +525,7 @@ fn eat_alterable<'a>(t: &'a [Token<'a>], word_lut: &WordLut) -> Result<NodeAndRe
498 525
                     Node::List(ns, _) => Node::List(ns, meta),
499 526
                     Node::Vector(ns, _) => Node::Vector(ns, meta),
500 527
                     Node::Float(f, s, _) => Node::Float(f, s, meta),
528
+                    Node::FromName(s, i, _) => Node::FromName(s, i, meta),
501 529
                     Node::Name(s, i, _) => Node::Name(s, i, meta),
502 530
                     Node::Label(s, i, _) => Node::Label(s, i, meta),
503 531
                     Node::String(s, i, _) => Node::String(s, i, meta),
@@ -562,6 +590,11 @@ fn eat_token<'a>(
562 590
                     node: Node::Label(t, ti, meta),
563 591
                     tokens: &tokens[2..],
564 592
                 })
593
+            } else if tokens.len() > 1 && tokens[1] == Token::Dot {
594
+                Ok(NodeAndRemainder {
595
+                    node: Node::FromName(t, ti, meta),
596
+                    tokens: &tokens[2..],
597
+                })
565 598
             } else {
566 599
                 Ok(NodeAndRemainder {
567 600
                     node: Node::Name(t, ti, meta),
@@ -798,4 +831,18 @@ mod tests {
798 831
             )]
799 832
         );
800 833
     }
834
+
835
+    #[test]
836
+    fn test_parser_from_name() {
837
+        assert_eq!(
838
+            ast("(some-vector.vector/length)"),
839
+            [Node::List(
840
+                vec![
841
+                    Node::FromName("some-vector".to_string(), Iname::new(0), None),
842
+                    Node::Name("vector/length".to_string(), Iname::from(Native::VectorLength), None),
843
+                ],
844
+                None
845
+            )]
846
+        );
847
+    }
801 848
 }

+ 1
- 0
core/src/unparser.rs View File

@@ -207,6 +207,7 @@ fn format_node_value(node: &Node) -> Result<String> {
207 207
             Err(Error::Unparser)
208 208
         }
209 209
         Node::Float(_, s, _) => Ok(s.to_string()),
210
+        Node::FromName(s, _, _) => Ok(s.to_string() + "."),
210 211
         Node::Name(s, _, _) => Ok(s.to_string()),
211 212
         Node::Label(s, _, _) => Ok(s.to_string() + ":"),
212 213
         Node::String(s, _, _) => Ok("\"".to_owned() + &s.to_string() + "\""),

Loading…
Cancel
Save