1#![warn(clippy::all)]
3#![feature(decl_macro)]
4
5use cl_ast::Sym;
6use convalue::ConValue;
7use env::Environment;
8use error::{Error, ErrorKind, IResult};
9use interpret::Interpret;
10
11pub trait Callable {
13 fn call(&self, interpreter: &mut Environment, args: &[ConValue]) -> IResult<ConValue>;
16 fn name(&self) -> Sym;
18}
19
20pub mod convalue;
21
22pub mod interpret;
23
24pub mod function;
25
26pub mod constructor {
27 use cl_ast::Sym;
28
29 use crate::{
30 Callable,
31 convalue::ConValue,
32 env::Environment,
33 error::{Error, IResult},
34 };
35
36 #[derive(Clone, Copy, Debug)]
37 pub struct Constructor {
38 pub name: Sym,
39 pub arity: u32,
40 }
41
42 impl Callable for Constructor {
43 fn call(&self, _env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
44 let &Self { name, arity } = self;
45 if arity as usize == args.len() {
46 Ok(ConValue::TupleStruct(name, Box::new(args.into())))
47 } else {
48 Err(Error::ArgNumber(arity as usize, args.len()))
49 }
50 }
51
52 fn name(&self) -> cl_ast::Sym {
53 "tuple-constructor".into()
54 }
55 }
56}
57
58pub mod closure;
59
60pub mod builtin;
61
62pub mod pattern;
63
64pub mod env;
65
66pub mod modules {
67 use crate::env::StackBinds;
68 use cl_ast::{PathPart, Sym};
69 use std::collections::HashMap;
70
71 #[derive(Clone, Copy, Debug)]
73 pub struct ModuleNode<'tree> {
74 tree: &'tree ModuleTree,
75 index: usize,
76 }
77
78 #[derive(Debug)]
80 pub struct ModuleNodeMut<'tree> {
81 tree: &'tree mut ModuleTree,
82 index: usize,
83 }
84
85 macro_rules! module_node_impl {
86 () => {
87 pub fn index(self) -> usize {
89 self.index
90 }
91 pub fn parent(self) -> Option<Self> {
93 let parent = self.tree.parent(self.index)?;
94 Some(Self { index: parent, ..self })
95 }
96 pub fn selfty(self) -> Option<Self> {
98 let selfty = self.tree.selfty(self.index)?;
99 Some(Self { index: selfty, ..self })
100 }
101 pub fn child(self, name: &Sym) -> Option<Self> {
103 let child = self.tree.child(self.index, name)?;
104 Some(Self { index: child, ..self })
105 }
106 pub fn item(self, name: &Sym) -> Option<usize> {
108 self.tree.items(self.index)?.get(name).copied()
109 }
110 pub fn is_ty(self) -> Option<bool> {
112 self.tree.is_ty.get(self.index).copied()
113 }
114 pub fn children(&self) -> Option<&HashMap<Sym, usize>> {
116 self.tree.children(self.index)
117 }
118 pub fn items(&self) -> Option<&StackBinds> {
120 self.tree.items(self.index)
121 }
122 pub fn find(self, path: &[PathPart]) -> (Self, &[PathPart]) {
126 let (index, path) = self.tree.find(self.index, path);
127 (Self { index, ..self }, path)
128 }
129 pub fn find_item(&self, path: &[PathPart]) -> Option<usize> {
133 self.tree.find_item(self.index, path)
134 }
135 };
136 }
137
138 impl ModuleNode<'_> {
139 module_node_impl! {}
140 }
141
142 impl ModuleNodeMut<'_> {
143 module_node_impl! {}
144 pub fn add_child(self, name: Sym, is_ty: bool) -> Self {
146 let node = self.tree.add_child(self.index, name, is_ty);
147 self.tree.get_mut(node)
148 }
149 pub fn add_import(&mut self, name: Sym, child: usize) {
151 self.tree.add_import(self.index, name, child)
152 }
153 pub fn add_imports(&mut self, binds: HashMap<Sym, usize>) {
154 self.tree.add_imports(self.index, binds)
155 }
156 pub fn add_item(&mut self, name: Sym, stack_index: usize) {
158 self.tree.add_item(self.index, name, stack_index)
159 }
160 pub fn add_items(&mut self, binds: StackBinds) {
162 self.tree.add_items(self.index, binds)
163 }
164 pub fn as_ref(&self) -> ModuleNode<'_> {
166 let Self { tree, index } = self;
167 ModuleNode { tree, index: *index }
168 }
169 }
170
171 #[derive(Clone, Debug)]
172 pub struct ModuleTree {
173 parents: Vec<usize>,
174 children: Vec<HashMap<Sym, usize>>,
175 items: Vec<StackBinds>,
176 is_ty: Vec<bool>,
177 }
178
179 impl ModuleTree {
180 pub fn new() -> Self {
182 Self {
183 parents: vec![0],
184 children: vec![HashMap::new()],
185 items: vec![HashMap::new()],
186 is_ty: vec![false],
187 }
188 }
189
190 pub fn get(&self, index: usize) -> ModuleNode<'_> {
192 ModuleNode { tree: self, index }
193 }
194
195 pub fn get_mut(&mut self, index: usize) -> ModuleNodeMut<'_> {
197 ModuleNodeMut { tree: self, index }
198 }
199
200 pub fn add_child(&mut self, parent: usize, name: Sym, is_ty: bool) -> usize {
202 let index = self.parents.len();
203 self.children[parent].insert(name, index);
204 self.parents.push(parent);
205 self.children.push(HashMap::new());
206 self.is_ty.push(is_ty);
207 index
208 }
209
210 pub fn add_item(&mut self, node: usize, name: Sym, stack_index: usize) {
212 self.items[node].insert(name, stack_index);
213 }
214
215 pub fn add_import(&mut self, parent: usize, name: Sym, child: usize) {
217 self.children[parent].insert(name, child);
218 }
219
220 pub fn add_items(&mut self, node: usize, binds: StackBinds) {
222 self.items[node].extend(binds);
223 }
224
225 pub fn add_imports(&mut self, node: usize, binds: HashMap<Sym, usize>) {
227 self.children[node].extend(binds);
228 }
229
230 pub fn parent(&self, node: usize) -> Option<usize> {
232 if node == 0 {
233 return None;
234 }
235 self.parents.get(node).copied()
236 }
237
238 pub fn selfty(&self, node: usize) -> Option<usize> {
240 if self.is_ty[node] {
241 return Some(node);
242 }
243 self.selfty(self.parent(node)?)
244 }
245
246 pub fn child(&self, node: usize, id: &Sym) -> Option<usize> {
248 self.children[node].get(id).copied()
249 }
250
251 pub fn item(&self, node: usize, name: &Sym) -> Option<usize> {
253 self.items.get(node).and_then(|map| map.get(name).copied())
254 }
255
256 pub fn children(&self, node: usize) -> Option<&HashMap<Sym, usize>> {
258 self.children.get(node)
259 }
260
261 pub fn items(&self, node: usize) -> Option<&StackBinds> {
263 self.items.get(node)
264 }
265
266 pub fn find<'p>(&self, node: usize, path: &'p [PathPart]) -> (usize, &'p [PathPart]) {
270 match path {
271 [PathPart::SuperKw, tail @ ..] => match self.parent(node) {
272 Some(node) => self.find(node, tail),
273 None => (node, path),
274 },
275 [PathPart::Ident(name), tail @ ..] => match self.child(node, name) {
276 Some(node) => self.find(node, tail),
277 None => (node, path),
278 },
279 [PathPart::SelfTy, tail @ ..] => match self.selfty(node) {
280 Some(node) => self.find(node, tail),
281 None => (node, path),
282 },
283 [] => (node, path),
284 }
285 }
286
287 pub fn find_item(&self, node: usize, path: &[PathPart]) -> Option<usize> {
291 let (node, [PathPart::Ident(name)]) = self.find(node, path) else {
292 return None;
293 };
294 self.item(node, name)
295 }
296 }
297
298 impl Default for ModuleTree {
299 fn default() -> Self {
300 Self::new()
301 }
302 }
303}
304
305pub mod collector {
306 use std::ops::{Deref, DerefMut};
307
308 use crate::{
309 convalue::ConValue,
310 env::Environment,
311 modules::{ModuleNode, ModuleNodeMut},
312 };
313 use cl_ast::{
314 ast_visitor::{Visit, Walk},
315 *,
316 };
317
318 pub struct Collector<'env> {
319 module: usize,
320 env: &'env mut Environment,
321 }
322
323 impl Collector<'_> {
324 pub fn as_node(&self) -> ModuleNode<'_> {
325 self.env.modules().get(self.module)
326 }
327
328 pub fn as_node_mut(&mut self) -> ModuleNodeMut<'_> {
329 self.env.modules_mut().get_mut(self.module)
330 }
331
332 pub fn scope(&mut self, name: Sym, is_ty: bool, f: impl Fn(&mut Collector<'_>)) {
333 let module = match self.as_node_mut().child(&name) {
334 Some(m) => m,
335 None => self.as_node_mut().add_child(name, is_ty),
336 }
337 .index();
338
339 let mut frame = self.env.frame(name.to_ref());
340 f(&mut Collector { env: &mut frame, module });
341 let binds = frame.into_binds().unwrap_or_default();
342
343 self.modules_mut().add_items(module, binds);
344 }
345
346 pub fn in_foreign_scope<F, T>(&mut self, path: &[PathPart], f: F) -> Option<T>
347 where F: Fn(&mut Collector<'_>) -> T {
348 let (module, []) = self.env.modules_mut().find(self.module, path) else {
349 return None;
350 };
351
352 let mut frame = self.env.frame("impl");
353 let out = f(&mut Collector { env: &mut frame, module });
354 let binds = frame.into_binds().unwrap_or_default();
355
356 self.env.modules_mut().add_items(module, binds);
357 Some(out)
358 }
359 }
360
361 impl<'env> Deref for Collector<'env> {
362 type Target = Environment;
363 fn deref(&self) -> &Self::Target {
364 self.env
365 }
366 }
367
368 impl DerefMut for Collector<'_> {
369 fn deref_mut(&mut self) -> &mut Self::Target {
370 self.env
371 }
372 }
373
374 impl<'a, 'env> Visit<'a> for Collector<'env> {
375 fn visit_file(&mut self, value: &'a File) {
376 let mut sorter = ItemSorter::default();
377 sorter.visit(value);
378 sorter.visit_all(self);
379 }
380 fn visit_block(&mut self, value: &'a Block) {
381 let mut sorter = ItemSorter::default();
382 sorter.visit(value);
383 sorter.visit_all(self);
384 }
385 fn visit_module(&mut self, value: &'a cl_ast::Module) {
386 self.scope(value.name, false, |scope| value.children(scope));
387 }
388 fn visit_alias(&mut self, value: &'a cl_ast::Alias) {
389 let Alias { name, from } = value;
390 match from.as_ref().map(Box::as_ref) {
391 Some(Ty { kind: TyKind::Path(path), .. }) => {
392 let mut node = if path.absolute {
393 self.modules_mut().get_mut(0)
394 } else {
395 self.as_node_mut()
396 };
397 if let Some(item) = node.find_item(&path.parts) {
398 node.add_item(*name, item);
399 }
400 }
401 Some(other) => todo!("Type expressions in the collector: {other}"),
402 None => self.scope(*name, true, |_| {}),
403 }
404 }
405 fn visit_enum(&mut self, value: &'a cl_ast::Enum) {
406 let Enum { name, gens: _, variants } = value;
407
408 self.scope(*name, true, |frame| {
409 for (idx, Variant { name, kind, body }) in variants.iter().enumerate() {
410 frame.visit(body);
411 frame.scope(*name, false, |frame| {
412 frame.bind("__discriminant", idx as isize);
413 match kind {
414 StructKind::Empty => {
415 frame.insert_tup_constructor("call".into(), 0);
416 frame.bind("__nmemb", ConValue::Int(0));
417 }
418 StructKind::Tuple(args) => {
419 frame.insert_tup_constructor("call".into(), args.len());
421 frame.bind("__nmemb", ConValue::Int(args.len() as _));
422 }
423 StructKind::Struct(members) => {
424 for (idx, memb) in members.iter().enumerate() {
426 let StructMember { vis: _, name, ty: _ } = memb;
427 frame.bind(*name, idx as isize);
428 }
429 frame.bind("__nmemb", ConValue::Int(members.len() as _));
430 }
431 }
432 });
433 }
434 });
435 }
436 fn visit_struct(&mut self, value: &'a cl_ast::Struct) {
437 let Struct { name, gens: _, kind } = value;
438
439 self.scope(*name, true, |frame| {
440 match kind {
441 StructKind::Empty => {
442 frame.insert_tup_constructor("call".into(), 0);
443 frame.bind("__nmemb", ConValue::Int(0));
444 }
445 StructKind::Tuple(args) => {
446 frame.insert_tup_constructor("call".into(), args.len());
448 frame.bind("__nmemb", ConValue::Int(args.len() as _));
449 }
450 StructKind::Struct(members) => {
451 for (idx, memb) in members.iter().enumerate() {
453 let StructMember { vis: _, name, ty: _ } = memb;
454 frame.bind(*name, idx as isize);
455 }
456 frame.bind("__nmemb", ConValue::Int(members.len() as _));
457 }
458 }
459 });
460 }
461 fn visit_const(&mut self, value: &'a cl_ast::Const) {
462 let Const { name, ty: _, init } = value;
463 self.visit(init);
464 self.bind(*name, ());
465 }
466 fn visit_static(&mut self, value: &'a cl_ast::Static) {
467 let Static { mutable: _, name, ty: _, init } = value;
468 self.visit(init);
469 self.bind(*name, ());
470 }
471 fn visit_function(&mut self, value: &'a cl_ast::Function) {
472 let Function { name, gens: _, sign: _, bind: _, body } = value;
473 self.scope(*name, false, |scope| {
474 scope.visit(body);
475 let f = crate::function::Function::new(value);
476 scope.bind("call", f);
477 });
478 }
479 fn visit_impl(&mut self, value: &'a cl_ast::Impl) {
480 let Impl { gens: _, target: ImplKind::Type(Ty { kind: TyKind::Path(name), .. }), body } =
481 value
482 else {
483 eprintln!("TODO: impl X for Ty");
484 return;
485 };
486 self.in_foreign_scope(&name.parts, |scope| {
487 body.visit_in(scope);
488 });
489 }
490 fn visit_use(&mut self, value: &'a cl_ast::Use) {
491 fn traverse(dest: &mut Collector<'_>, node: usize, tree: &UseTree) {
492 match tree {
493 UseTree::Tree(ts) => ts.iter().for_each(|tree| traverse(dest, node, tree)),
494 UseTree::Path(PathPart::Ident(name), tree) => {
495 if let (node, []) = dest.modules().find(node, &[PathPart::Ident(*name)]) {
496 traverse(dest, node, tree)
497 }
498 }
499 UseTree::Path(PathPart::SuperKw, tree) => {
500 if let Some(node) = dest.modules().parent(node) {
501 traverse(dest, node, tree)
502 }
503 }
504 UseTree::Path(PathPart::SelfTy, tree) => {
505 if let Some(node) = dest.modules().selfty(node) {
506 traverse(dest, node, tree)
507 }
508 }
509 UseTree::Alias(name, as_name) => {
510 if let Some(child) = dest.modules().child(node, name) {
511 dest.as_node_mut().add_import(*as_name, child);
512 }
513 if let Some(item) = dest.modules().item(node, name) {
514 dest.as_node_mut().add_item(*as_name, item);
515 }
516 }
517 UseTree::Name(name) => {
518 if let Some(child) = dest.modules().child(node, name) {
519 dest.as_node_mut().add_import(*name, child);
520 }
521 if let Some(item) = dest.modules().item(node, name) {
522 dest.as_node_mut().add_item(*name, item);
523 }
524 }
525 UseTree::Glob => {
526 let &mut Collector { module, ref mut env } = dest;
527 if let Some(children) = env.modules().children(node) {
528 for (name, index) in children.clone() {
529 env.modules_mut().add_import(module, name, index);
530 }
531 }
532 if let Some(items) = env.modules().items(node).cloned() {
533 env.modules_mut().add_items(node, items);
534 }
535 }
536 }
537 }
538
539 let Use { absolute, tree } = value;
540 let node = if *absolute { 0 } else { self.module };
541 traverse(self, node, tree);
542 }
543 }
544
545 #[derive(Debug, Default)]
575 struct ItemSorter<'ast> {
576 modules: Vec<&'ast Module>,
577 structs: Vec<&'ast Struct>,
578 enums: Vec<&'ast Enum>,
579 aliases: Vec<&'ast Alias>,
580 consts: Vec<&'ast Const>,
581 statics: Vec<&'ast Static>,
582 functions: Vec<&'ast Function>,
583 impls: Vec<&'ast Impl>,
584 imports: Vec<&'ast Use>,
585 }
586
587 impl<'a> ItemSorter<'a> {
588 fn visit_all<V: Visit<'a>>(&self, v: &mut V) {
589 let Self {
590 modules,
591 aliases,
592 enums,
593 structs,
594 consts,
595 statics,
596 functions,
597 impls,
598 imports,
599 } = self;
600
601 for item in modules {
603 item.visit_in(v);
604 }
605 for item in structs {
607 item.visit_in(v);
608 }
609 for item in enums {
610 item.visit_in(v);
611 }
612 for item in aliases {
613 item.visit_in(v);
614 }
615 for item in consts {
618 item.visit_in(v);
619 }
620 for item in statics {
621 item.visit_in(v);
622 }
623 for item in functions {
624 item.visit_in(v);
625 }
626 for item in impls {
628 item.visit_in(v);
629 }
630 for item in imports {
632 item.visit_in(v);
633 }
634 }
635 }
636
637 impl<'a> Visit<'a> for ItemSorter<'a> {
638 fn visit_module(&mut self, value: &'a cl_ast::Module) {
639 self.modules.push(value);
640 }
641 fn visit_alias(&mut self, value: &'a cl_ast::Alias) {
642 self.aliases.push(value);
643 }
644 fn visit_enum(&mut self, value: &'a cl_ast::Enum) {
645 self.enums.push(value);
646 }
647 fn visit_struct(&mut self, value: &'a cl_ast::Struct) {
648 self.structs.push(value);
649 }
650 fn visit_const(&mut self, value: &'a cl_ast::Const) {
651 self.consts.push(value);
652 }
653 fn visit_static(&mut self, value: &'a cl_ast::Static) {
654 self.statics.push(value);
655 }
656 fn visit_function(&mut self, value: &'a cl_ast::Function) {
657 self.functions.push(value);
658 }
659 fn visit_impl(&mut self, value: &'a cl_ast::Impl) {
660 self.impls.push(value);
661 }
662 fn visit_use(&mut self, value: &'a cl_ast::Use) {
663 self.imports.push(value);
664 }
665 }
666}
667
668pub mod error;
669
670#[cfg(test)]
671mod tests;