1use std::sync::Arc;
10
11use kdl::{KdlDocument, KdlEntry, KdlNode};
12use miette::{Diagnostic, NamedSource, SourceSpan};
13use nom::branch::alt;
14use nom::bytes::complete::tag;
15use nom::character::complete::{alpha1, alphanumeric1};
16use nom::combinator::{all_consuming, cut, opt, recognize};
17use nom::error::{context, VerboseError};
18use nom::multi::{many0, many0_count, separated_list1};
19use nom::sequence::{delimited, pair, preceded, separated_pair};
20use nom::{Finish, IResult};
21use thiserror::Error;
22use tracing::trace;
23
24use crate::spanned::Spanned;
25use crate::types::{PrimitiveTy, PRIMITIVES};
26use crate::{Compiler, Result};
27
28pub type StableMap<K, V> = linked_hash_map::LinkedHashMap<K, V>;
29
30#[derive(Debug, Clone)]
32pub struct Ident {
33 pub was_blank: bool,
38 pub val: Spanned<String>,
40}
41
42impl std::cmp::PartialEq for Ident {
43 fn eq(&self, other: &Self) -> bool {
44 self.val == other.val
45 }
46}
47impl std::cmp::PartialEq<String> for Ident {
48 fn eq(&self, other: &String) -> bool {
49 self.val.as_str() == other
50 }
51}
52impl std::cmp::PartialEq<str> for Ident {
53 fn eq(&self, other: &str) -> bool {
54 self.val.as_str() == other
55 }
56}
57impl std::cmp::Eq for Ident {}
58impl std::cmp::PartialOrd for Ident {
59 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
60 Some(self.cmp(other))
61 }
62}
63impl std::cmp::Ord for Ident {
64 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
65 self.val.cmp(&other.val)
66 }
67}
68impl std::hash::Hash for Ident {
69 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
70 self.val.hash(state);
71 }
72}
73impl std::borrow::Borrow<str> for Ident {
74 fn borrow(&self) -> &str {
75 &self.val
76 }
77}
78
79impl std::ops::Deref for Ident {
80 type Target = Spanned<String>;
81 fn deref(&self) -> &Self::Target {
82 &self.val
83 }
84}
85impl From<String> for Ident {
86 fn from(val: String) -> Self {
87 Self::new(Spanned::from(val))
88 }
89}
90
91impl Ident {
92 fn new(val: Spanned<String>) -> Self {
93 Self {
94 val,
95 was_blank: false,
96 }
97 }
98 fn with_span(val: String, span: SourceSpan) -> Self {
99 Self {
100 val: Spanned::new(val, span),
101 was_blank: false,
102 }
103 }
104}
105
106impl std::fmt::Display for Ident {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 self.val.fmt(f)
109 }
110}
111
112#[derive(Debug, Error, Diagnostic)]
114#[error("{message}")]
115pub struct KdlScriptParseError {
116 pub message: String,
117 #[source_code]
118 pub src: Arc<NamedSource>,
119 #[label]
120 pub span: SourceSpan,
121 #[help]
122 pub help: Option<String>,
123}
124
125#[derive(Debug, Clone)]
127pub struct ParsedProgram {
128 pub tys: StableMap<Ident, TyDecl>,
130 pub funcs: StableMap<Ident, FuncDecl>,
132 pub builtin_funcs_start: usize,
134}
135
136#[derive(Debug, Clone)]
138pub enum TyDecl {
139 Struct(StructDecl),
141 Union(UnionDecl),
143 Enum(EnumDecl),
145 Tagged(TaggedDecl),
147 Alias(AliasDecl),
149 Pun(PunDecl),
151}
152
153#[derive(Debug, Clone)]
157pub enum Tydent {
158 Name(Ident),
160 Array(Box<Spanned<Tydent>>, u64),
162 Ref(Box<Spanned<Tydent>>),
164 Empty,
166}
167
168#[derive(Debug, Clone, PartialEq, Eq, Hash)]
180pub enum Attr {
181 Packed(AttrPacked),
183 Align(AttrAligned),
185 Repr(AttrRepr),
187 Passthrough(AttrPassthrough),
189}
190
191#[derive(Debug, Clone, PartialEq, Eq, Hash)]
199pub struct AttrPacked {}
200
201#[derive(Debug, Clone, PartialEq, Eq, Hash)]
205pub struct AttrAligned {
206 pub align: IntExpr,
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Hash)]
210pub struct AttrRepr {
211 pub reprs: Vec<Repr>,
212}
213
214#[derive(Debug, Clone, PartialEq, Eq, Hash)]
215pub enum Repr {
216 Primitive(PrimitiveTy),
217 Lang(LangRepr),
218 Transparent,
219}
220
221#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize)]
222pub enum LangRepr {
223 Rust,
224 C,
225}
226impl std::fmt::Display for LangRepr {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 let s = match self {
229 LangRepr::Rust => "rust",
230 LangRepr::C => "c",
231 };
232 s.fmt(f)
233 }
234}
235impl std::str::FromStr for LangRepr {
236 type Err = String;
237 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
238 match s {
239 "rust" => Ok(Self::Rust),
240 "c" => Ok(Self::C),
241 _ => Err(format!("unknown lang repr {s}")),
242 }
243 }
244}
245
246#[derive(Debug, Clone, PartialEq, Eq, Hash)]
250pub struct AttrPassthrough(pub Spanned<String>);
251
252#[derive(Debug, Clone)]
259pub struct StructDecl {
260 pub name: Ident,
262 pub fields: Vec<TypedVar>,
264 pub attrs: Vec<Attr>,
266}
267
268#[derive(Debug, Clone)]
273pub struct UnionDecl {
274 pub name: Ident,
276 pub fields: Vec<TypedVar>,
278 pub attrs: Vec<Attr>,
279}
280
281#[derive(Debug, Clone)]
286pub struct EnumDecl {
287 pub name: Ident,
288 pub variants: Vec<EnumVariant>,
289 pub attrs: Vec<Attr>,
290}
291
292#[derive(Debug, Clone)]
294pub struct EnumVariant {
295 pub name: Ident,
296 pub val: Option<IntExpr>,
299}
300
301#[derive(Debug, Clone)]
306pub struct TaggedDecl {
307 pub name: Ident,
308 pub variants: Vec<TaggedVariant>,
309 pub attrs: Vec<Attr>,
310}
311
312#[derive(Debug, Clone)]
314pub struct TaggedVariant {
315 pub name: Ident,
316 pub fields: Option<Vec<TypedVar>>,
317}
318
319#[derive(Debug, Clone)]
321pub struct PunDecl {
322 pub name: Ident,
323 pub blocks: Vec<PunBlock>,
324 pub attrs: Vec<Attr>,
325}
326
327#[derive(Debug, Clone)]
329pub struct PunBlock {
330 pub selector: PunSelector,
331 pub decl: TyDecl,
332}
333
334#[derive(Debug, Clone, PartialEq, Eq, Hash)]
336pub enum PunSelector {
337 Any(Vec<PunSelector>),
339 All(Vec<PunSelector>),
341 Lang(Spanned<String>),
343 Default,
345}
346
347#[derive(Debug, Clone)]
349pub struct PunEnv {
350 pub lang: String,
352 }
356
357impl PunSelector {
358 pub fn matches(&self, env: &PunEnv) -> bool {
360 use PunSelector::*;
361 match self {
362 Any(args) => args.iter().any(|s| s.matches(env)),
363 All(args) => args.iter().all(|s| s.matches(env)),
364 Lang(lang) => env.lang == **lang,
365 Default => true,
366 }
367 }
368}
369
370#[derive(Debug, Clone)]
372pub struct AliasDecl {
373 pub name: Ident,
374 pub alias: Spanned<Tydent>,
375 pub attrs: Vec<Attr>,
376}
377
378#[derive(Debug, Clone)]
380pub struct TypedVar {
381 pub name: Option<Ident>,
382 pub ty: Spanned<Tydent>,
383}
384
385#[derive(Debug, Clone)]
387pub struct FuncDecl {
388 pub name: Ident,
389 pub inputs: Vec<TypedVar>,
390 pub outputs: Vec<TypedVar>,
391 pub attrs: Vec<Attr>,
392 #[cfg(feature = "eval")]
393 pub body: Vec<Stmt>,
394}
395
396struct Parser<'a> {
398 src: Arc<NamedSource>,
400 ast: &'a KdlDocument,
401}
402
403pub fn parse_kdl_script(
405 _comp: &mut Compiler,
406 src: Arc<NamedSource>,
407 ast: &KdlDocument,
408) -> Result<ParsedProgram> {
409 let mut parser = Parser { src, ast };
410 parser.parse()
411}
412
413impl Parser<'_> {
414 fn parse(&mut self) -> Result<ParsedProgram> {
416 trace!("parsing");
417
418 let mut program = self.parse_module(self.ast)?;
419 #[cfg(feature = "eval")]
420 program.add_builtin_funcs()?;
421
422 Ok(program)
423 }
424
425 fn parse_module(&mut self, doc: &KdlDocument) -> Result<ParsedProgram> {
427 let mut funcs = StableMap::new();
428 let mut tys = StableMap::new();
429
430 let mut cur_attrs = vec![];
431 for node in doc.nodes() {
432 let name = node.name().value();
433
434 if name.starts_with('@') {
436 cur_attrs.push(self.attr(node)?);
437 continue;
438 }
439
440 let attrs = std::mem::take(&mut cur_attrs);
442
443 match name {
445 "fn" => {
446 let func = self.func_decl(node, attrs)?;
447 funcs.insert(func.name.clone(), func);
448 }
449 "struct" => {
450 let ty = self.struct_decl(node, attrs)?;
451 let old = tys.insert(ty.name.clone(), TyDecl::Struct(ty));
452 assert!(old.is_none(), "duplicate type def");
453 }
454 "union" => {
455 let ty = self.union_decl(node, attrs)?;
456 let old = tys.insert(ty.name.clone(), TyDecl::Union(ty));
457 assert!(old.is_none(), "duplicate type def");
458 }
459 "enum" => {
460 let ty = self.enum_decl(node, attrs)?;
461 let old = tys.insert(ty.name.clone(), TyDecl::Enum(ty));
462 assert!(old.is_none(), "duplicate type def");
463 }
464 "tagged" => {
465 let ty = self.tagged_decl(node, attrs)?;
466 let old = tys.insert(ty.name.clone(), TyDecl::Tagged(ty));
467 assert!(old.is_none(), "duplicate type def");
468 }
469 "alias" => {
470 let ty = self.alias_decl(node, attrs)?;
471 let old = tys.insert(ty.name.clone(), TyDecl::Alias(ty));
472 assert!(old.is_none(), "duplicate type def");
473 }
474 "pun" => {
475 let ty = self.pun_decl(node, attrs)?;
476 let old = tys.insert(ty.name.clone(), TyDecl::Pun(ty));
477 assert!(old.is_none(), "duplicate type def");
478 }
479 x => {
480 return Err(KdlScriptParseError {
481 message: format!("I don't know what a '{x}' is"),
482 src: self.src.clone(),
483 span: *node.name().span(),
484 help: None,
485 })?;
486 }
487 }
488 }
489
490 let builtin_funcs_start = funcs.len();
492 Ok(ParsedProgram {
493 tys,
494 funcs,
495 builtin_funcs_start,
496 })
497 }
498
499 fn struct_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<StructDecl> {
501 trace!("struct decl");
502 let name = self.one_string(node, "type name")?;
503 let name = self.ident(name)?;
504 let fields = self.typed_var_children(node)?;
505
506 Ok(StructDecl {
507 name,
508 fields,
509 attrs,
510 })
511 }
512
513 fn union_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<UnionDecl> {
515 trace!("union decl");
516 let name = self.one_string(node, "type name")?;
517 let name = self.ident(name)?;
518 let fields = self.typed_var_children(node)?;
519
520 Ok(UnionDecl {
521 name,
522 fields,
523 attrs,
524 })
525 }
526
527 fn enum_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<EnumDecl> {
529 trace!("enum decl");
530 let name = self.one_string(node, "type name")?;
531 let name = self.ident(name)?;
532 let variants = self.enum_variant_children(node)?;
533
534 Ok(EnumDecl {
535 name,
536 variants,
537 attrs,
538 })
539 }
540
541 fn tagged_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<TaggedDecl> {
543 trace!("enum decl");
544 let name = self.one_string(node, "type name")?;
545 let name = self.ident(name)?;
546 let variants = self.tagged_variant_children(node)?;
547
548 Ok(TaggedDecl {
549 name,
550 variants,
551 attrs,
552 })
553 }
554
555 fn pun_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<PunDecl> {
557 let name = self.one_string(node, "type name")?;
558 let name = self.ident(name)?;
559
560 let mut blocks = vec![];
562 for item in node.children().into_iter().flat_map(|d| d.nodes()) {
563 let item_name = item.name().value();
564 match item_name {
565 "lang" => {
566 let langs = self.string_list(item.entries())?;
567 if langs.is_empty() {
568 let node_ident = item.name().span();
569 let after_ident = node_ident.offset() + node_ident.len();
570 return Err(KdlScriptParseError {
571 message: "Hey I need a lang name (string) here!".to_string(),
572 src: self.src.clone(),
573 span: (after_ident..after_ident).into(),
574 help: None,
575 })?;
576 }
577 let final_ty = self.pun_block(item, &name)?;
578 blocks.push(PunBlock {
579 selector: PunSelector::Any(
580 langs.into_iter().map(PunSelector::Lang).collect(),
581 ),
582 decl: final_ty,
583 });
584 }
585 "default" => {
586 self.no_args(item)?;
587 let final_ty = self.pun_block(item, &name)?;
588 blocks.push(PunBlock {
589 selector: PunSelector::Default,
590 decl: final_ty,
591 });
592 }
593 x => {
594 return Err(KdlScriptParseError {
595 message: format!("I don't know what a '{x}' is here"),
596 src: self.src.clone(),
597 span: *item.name().span(),
598 help: None,
599 })?;
600 }
601 }
602 }
603
604 Ok(PunDecl {
605 name,
606 blocks,
607 attrs,
608 })
609 }
610
611 fn pun_block(&mut self, block: &KdlNode, final_ty_name: &Ident) -> Result<TyDecl> {
618 if let Some(doc) = block.children() {
619 let defs = self.parse_module(doc)?;
621
622 if let Some((_name, func)) = defs.funcs.iter().next() {
624 return Err(KdlScriptParseError {
625 message: "puns can't contain function decls".to_string(),
626 src: self.src.clone(),
627 span: Spanned::span(&func.name),
628 help: None,
629 })?;
630 }
631
632 let mut final_ty = None;
633
634 for (ty_name, ty) in defs.tys {
636 if &ty_name == final_ty_name {
637 final_ty = Some(ty);
639 } else {
640 return Err(KdlScriptParseError {
641 message: "pun declared a type other than what it should have".to_string(),
642 src: self.src.clone(),
643 span: Spanned::span(&ty_name),
644 help: None,
645 })?;
646 }
647 }
648
649 if let Some(ty) = final_ty {
651 Ok(ty)
652 } else {
653 Err(KdlScriptParseError {
654 message: "pun block failed to define the type it puns!".to_string(),
655 src: self.src.clone(),
656 span: *block.span(),
657 help: None,
658 })?
659 }
660 } else {
661 Err(KdlScriptParseError {
662 message: "pun blocks need bodies".to_string(),
663 src: self.src.clone(),
664 span: *block.span(),
665 help: None,
666 })?
667 }
668 }
669
670 fn alias_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<AliasDecl> {
672 let name = self.string_at(node, "type name", 0)?;
673 let name = self.ident(name)?;
674 let alias_str = self.string_at(node, "type name", 1)?;
675 let alias = self.tydent(&alias_str)?;
676
677 Ok(AliasDecl { name, alias, attrs })
678 }
679
680 fn func_decl(&mut self, node: &KdlNode, attrs: Vec<Attr>) -> Result<FuncDecl> {
682 trace!("fn");
683 let name = self.one_string(node, "function name")?;
684 let name = self.ident(name)?;
685 let mut inputs = vec![];
686 let mut outputs = vec![];
687 #[cfg(feature = "eval")]
688 let mut body = vec![];
689
690 let mut reached_body = false;
691 let mut input_span = None;
692 let mut output_span = None;
693 for stmt in node.children().into_iter().flat_map(|d| d.nodes()) {
694 match stmt.name().value() {
695 "inputs" => {
696 trace!("fn input");
697 if reached_body {
698 return Err(KdlScriptParseError {
699 message: "input declaration must come before the body".to_string(),
700 src: self.src.clone(),
701 span: *stmt.name().span(),
702 help: None,
703 })?;
704 }
705 if let Some(_old_input) = input_span {
706 return Err(KdlScriptParseError {
707 message: "duplicate input block".to_string(),
708 src: self.src.clone(),
709 span: *stmt.name().span(),
710 help: None,
711 })?;
712 }
713 if let Some(_old_output) = output_span {
714 return Err(KdlScriptParseError {
715 message: "It's confusing to declare inputs after outputs".to_string(),
716 src: self.src.clone(),
717 span: *stmt.name().span(),
718 help: Some("Move this before the output block".to_string()),
719 })?;
720 }
721 self.no_args(stmt)?;
722 inputs = self.typed_var_children(stmt)?;
723 input_span = Some(*stmt.name().span());
724 continue;
725 }
726 "outputs" => {
727 trace!("fn output");
728 if reached_body {
729 return Err(KdlScriptParseError {
730 message: "output declaration must come before the body".to_string(),
731 src: self.src.clone(),
732 span: *stmt.name().span(),
733 help: None,
734 })?;
735 }
736 if let Some(_old_output) = output_span {
737 return Err(KdlScriptParseError {
738 message: "duplicate output block".to_string(),
739 src: self.src.clone(),
740 span: *stmt.name().span(),
741 help: None,
742 })?;
743 }
744 self.no_args(stmt)?;
745 outputs = self.typed_var_children(stmt)?;
746 output_span = Some(*stmt.name().span());
747 continue;
748 }
749 x => {
750 #[cfg(feature = "eval")]
751 match x {
752 "let" => {
753 trace!("let stmt");
754 let name = self.string_at(stmt, "variable name", 0)?;
755 let name = self.ident(name)?;
756 let name = if &*name == "_" { None } else { Some(name) };
757 let expr = self.expr_rhs(stmt, 1)?;
758 body.push(Stmt::Let(LetStmt { var: name, expr }));
759 }
760 "return" => {
761 trace!("return stmt");
762 let expr = self.expr_rhs(stmt, 0)?;
763 body.push(Stmt::Return(ReturnStmt { expr }));
764 }
765 "print" => {
766 trace!("print stmt");
767 let expr = self.expr_rhs(stmt, 0)?;
768 body.push(Stmt::Print(PrintStmt { expr }));
769 }
770 x => {
771 return Err(KdlScriptParseError {
772 message: format!("I don't know what a '{x}' statement is"),
773 src: self.src.clone(),
774 span: *stmt.name().span(),
775 help: None,
776 })?;
777 }
778 }
779 #[cfg(not(feature = "eval"))]
780 return Err(KdlScriptParseError {
781 message: format!("I don't know what a '{x}' statement is"),
782 src: self.src.clone(),
783 span: *stmt.name().span(),
784 help: None,
785 })?;
786 }
787 }
788
789 reached_body = true;
790 }
791
792 Ok(FuncDecl {
793 name,
794 inputs,
795 outputs,
796 #[cfg(feature = "eval")]
797 body,
798 attrs,
799 })
800 }
801
802 fn attr(&mut self, attr: &KdlNode) -> Result<Attr> {
804 let attr = match attr.name().value() {
805 "@packed" => {
806 trace!("packed attr");
807 self.no_children(attr)?;
808 Attr::Packed(AttrPacked {})
809 }
810 "@align" => {
811 trace!("align attr");
812 let Some(e) = attr.entries().first() else {
813 return Err(KdlScriptParseError {
814 message: "align attr needs an integer argument".to_owned(),
815 src: self.src.clone(),
816 span: *attr.name().span(),
817 help: None,
818 })?;
819 };
820 let align = self.int_expr(e)?;
821 Attr::Align(AttrAligned { align })
822 }
823 "@repr" => {
824 trace!("repr attr");
825 let raw_reprs = self.string_list(attr.entries())?;
826 let mut reprs = vec![];
827 for raw_repr in raw_reprs {
828 let repr = match &**raw_repr {
829 "rust" => Repr::Lang(LangRepr::Rust),
830 "c" => Repr::Lang(LangRepr::C),
831 "transparent" => Repr::Transparent,
832 name => {
833 let mut prim_repr = None;
834 for &(prim_name, prim) in PRIMITIVES {
835 if prim_name == name {
836 prim_repr = Some(prim);
837 }
838 }
839 let Some(prim_repr) = prim_repr else {
840 return Err(KdlScriptParseError {
841 message: "repr attr has unknown kind".to_owned(),
842 src: self.src.clone(),
843 span: *attr.name().span(),
844 help: None,
845 })?;
846 };
847 Repr::Primitive(prim_repr)
848 }
849 };
850 reprs.push(repr);
851 }
852 Attr::Repr(AttrRepr { reprs })
853 }
854 "@" => {
855 trace!("passthrough attr");
856 let val = self.one_string(attr, "attribute to pass through to target language")?;
857 Attr::Passthrough(AttrPassthrough(val))
858 }
859 x => {
860 return Err(KdlScriptParseError {
861 message: format!("I don't know what a '{x}' attribute is"),
862 src: self.src.clone(),
863 span: *attr.name().span(),
864 help: None,
865 })?;
866 }
867 };
868 Ok(attr)
869 }
870
871 fn string_list(&mut self, entries: &[KdlEntry]) -> Result<Vec<Spanned<String>>> {
873 entries
874 .iter()
875 .map(|e| -> Result<Spanned<String>> {
876 if e.name().is_some() {
877 return Err(KdlScriptParseError {
878 message: "Named values don't belong here, only strings".to_string(),
879 src: self.src.clone(),
880 span: *e.span(),
881 help: Some("try removing the name".to_owned()),
882 })?;
883 }
884 match e.value() {
885 kdl::KdlValue::RawString(s) | kdl::KdlValue::String(s) => {
886 Ok(Spanned::new(s.clone(), *e.span()))
887 }
888 _ => Err(KdlScriptParseError {
889 message: "This should be a string".to_string(),
890 src: self.src.clone(),
891 span: *e.span(),
892 help: Some("try adding quotes?".to_owned()),
893 })?,
894 }
895 })
896 .collect()
897 }
898
899 fn one_string(&mut self, node: &KdlNode, desc: &str) -> Result<Spanned<String>> {
901 let res = self.string_at(node, desc, 0)?;
902 let entries = node.entries();
903 if let Some(e) = entries.get(1) {
904 return Err(KdlScriptParseError {
905 message: format!("You have something extra after your {desc}"),
906 src: self.src.clone(),
907 span: *e.span(),
908 help: Some("remove this?".to_owned()),
909 })?;
910 }
911 Ok(res)
912 }
913
914 fn string_at(&mut self, node: &KdlNode, desc: &str, offset: usize) -> Result<Spanned<String>> {
916 let entries = node.entries();
917 if let Some(e) = entries.get(offset) {
918 if e.name().is_some() {
919 return Err(KdlScriptParseError {
920 message: "Named values don't belong here, only strings".to_string(),
921 src: self.src.clone(),
922 span: *e.span(),
923 help: Some("try removing the name".to_owned()),
924 })?;
925 }
926
927 match e.value() {
928 kdl::KdlValue::RawString(s) | kdl::KdlValue::String(s) => {
929 Ok(Spanned::new(s.clone(), *e.span()))
930 }
931 _ => Err(KdlScriptParseError {
932 message: format!("This should be a {desc} (string)"),
933 src: self.src.clone(),
934 span: *e.span(),
935 help: Some("try adding quotes".to_owned()),
936 })?,
937 }
938 } else {
939 let node_ident = node.name().span();
940 let after_ident = node_ident.offset() + node_ident.len();
941 Err(KdlScriptParseError {
942 message: format!("Hey I need a {desc} (string) here!"),
943 src: self.src.clone(),
944 span: (after_ident..after_ident).into(),
945 help: None,
946 })?
947 }
948 }
949
950 fn no_args(&mut self, node: &KdlNode) -> Result<()> {
952 if let Some(entry) = node.entries().first() {
953 return Err(KdlScriptParseError {
954 message: "This shouldn't have arguments".to_string(),
955 src: self.src.clone(),
956 span: *entry.span(),
957 help: Some("delete them?".to_string()),
958 })?;
959 }
960 Ok(())
961 }
962
963 fn no_children(&mut self, node: &KdlNode) -> Result<()> {
965 if let Some(children) = node.children() {
966 return Err(KdlScriptParseError {
967 message: "These children should never have been born".to_string(),
968 src: self.src.clone(),
969 span: *children.span(),
970 help: Some("delete this block?".to_string()),
971 })?;
972 }
973 Ok(())
974 }
975
976 fn typed_var_children(&mut self, node: &KdlNode) -> Result<Vec<TypedVar>> {
978 node.children()
979 .into_iter()
980 .flat_map(|d| d.nodes())
981 .map(|var| {
982 let name = self.var_name_decl(var)?;
983 let ty_str = self.one_string(var, "type")?;
984 let ty = self.tydent(&ty_str)?;
985 self.no_children(var)?;
986 Ok(TypedVar { name, ty })
987 })
988 .collect()
989 }
990
991 fn enum_variant_children(&mut self, node: &KdlNode) -> Result<Vec<EnumVariant>> {
993 node.children()
994 .into_iter()
995 .flat_map(|d| d.nodes())
996 .map(|var| {
997 let name = var.name();
998 let name = Spanned::new(name.value().to_owned(), *name.span());
999 let name = self.ident(name)?;
1000 let entries = var.entries();
1001 let val = if let Some(e) = entries.first() {
1002 Some(self.int_expr(e)?)
1003 } else {
1004 None
1005 };
1006 if let Some(e) = entries.get(1) {
1007 return Err(KdlScriptParseError {
1008 message: "You have something extra after your enum case".to_string(),
1009 src: self.src.clone(),
1010 span: *e.span(),
1011 help: Some("remove this?".to_owned()),
1012 })?;
1013 }
1014 self.no_children(var)?;
1015 Ok(EnumVariant { name, val })
1016 })
1017 .collect()
1018 }
1019
1020 fn tagged_variant_children(&mut self, node: &KdlNode) -> Result<Vec<TaggedVariant>> {
1022 node.children()
1023 .into_iter()
1024 .flat_map(|d| d.nodes())
1025 .map(|var| {
1026 self.no_args(var)?;
1027 let name = var.name();
1028 let name = Spanned::new(name.value().to_owned(), *name.span());
1029 let name = self.ident(name)?;
1030 let fields = if var.children().is_some() {
1031 Some(self.typed_var_children(var)?)
1032 } else {
1033 None
1034 };
1035 Ok(TaggedVariant { name, fields })
1036 })
1037 .collect()
1038 }
1039
1040 fn var_name_decl(&mut self, var: &KdlNode) -> Result<Option<Ident>> {
1042 let name = var.name();
1043 let name = if name.value() == "_" {
1044 None
1045 } else {
1046 let name = self.ident(Spanned::new(name.value().to_owned(), *name.span()))?;
1047 Some(name)
1048 };
1049 Ok(name)
1050 }
1051
1052 fn tydent(&mut self, input: &Spanned<String>) -> Result<Spanned<Tydent>> {
1054 let (_, mut ty_ref) = all_consuming(context("a type", tydent))(input)
1055 .finish()
1056 .map_err(|_e| KdlScriptParseError {
1057 message: String::from("couldn't parse type"),
1058 src: self.src.clone(),
1059 span: Spanned::span(input),
1060 help: None,
1061 })?;
1062
1063 inherit_spans(&mut ty_ref, input);
1065 Ok(ty_ref)
1066 }
1067
1068 fn ident(&mut self, input: Spanned<String>) -> Result<Ident> {
1070 let (_, _) =
1071 all_consuming(context("a type", tydent))(&input).map_err(|_e| KdlScriptParseError {
1072 message: String::from("invalid identifier"),
1073 src: self.src.clone(),
1074 span: Spanned::span(&input),
1075 help: None,
1076 })?;
1077 Ok(Ident {
1078 val: input,
1079 was_blank: false,
1080 })
1081 }
1082
1083 fn int_expr(&mut self, entry: &KdlEntry) -> Result<IntExpr> {
1085 if entry.name().is_some() {
1086 return Err(KdlScriptParseError {
1087 message: "Named values don't belong here, only literals".to_string(),
1088 src: self.src.clone(),
1089 span: *entry.span(),
1090 help: Some("try removing the name".to_owned()),
1091 })?;
1092 }
1093 let val = match entry.value() {
1094 kdl::KdlValue::Base2(int)
1095 | kdl::KdlValue::Base8(int)
1096 | kdl::KdlValue::Base10(int)
1097 | kdl::KdlValue::Base16(int) => *int,
1098 _ => {
1099 return Err(KdlScriptParseError {
1100 message: String::from("must be an integer"),
1101 src: self.src.clone(),
1102 span: *entry.span(),
1103 help: None,
1104 })?;
1105 }
1106 };
1107 Ok(IntExpr {
1108 span: *entry.span(),
1109 val,
1110 })
1111 }
1112}
1113
1114fn inherit_spans(tydent: &mut Spanned<Tydent>, input: &Spanned<String>) {
1115 Spanned::clone_span_from(tydent, input);
1116 match &mut **tydent {
1117 Tydent::Name(ident) => {
1118 Spanned::clone_span_from(&mut ident.val, input);
1119 }
1120 Tydent::Array(elem_tydent, _) => {
1121 inherit_spans(elem_tydent, input);
1122 }
1123 Tydent::Ref(pointee_tydent) => {
1124 inherit_spans(pointee_tydent, input);
1125 }
1126 Tydent::Empty => {
1127 }
1129 }
1130}
1131
1132type NomResult<I, O> = IResult<I, O, VerboseError<I>>;
1135
1136fn tydent(input: &str) -> NomResult<&str, Spanned<Tydent>> {
1138 alt((tydent_ref, tydent_array, tydent_empty_tuple, tydent_named))(input)
1139}
1140
1141fn tydent_ref(input: &str) -> NomResult<&str, Spanned<Tydent>> {
1143 let (input, pointee_ty) = preceded(
1144 tag("&"),
1145 context("pointee type", cut(preceded(many0(unicode_space), tydent))),
1146 )(input)?;
1147 Ok((input, Spanned::from(Tydent::Ref(Box::new(pointee_ty)))))
1148}
1149
1150fn tydent_array(input: &str) -> NomResult<&str, Spanned<Tydent>> {
1152 let (input, (elem_ty, array_len)) = delimited(
1153 tag("["),
1154 cut(separated_pair(
1155 context(
1156 "an element type",
1157 delimited(many0(unicode_space), tydent, many0(unicode_space)),
1158 ),
1159 tag(";"),
1160 context(
1161 "an array length (integer)",
1162 delimited(many0(unicode_space), array_len, many0(unicode_space)),
1163 ),
1164 )),
1165 tag("]"),
1166 )(input)?;
1167 Ok((
1168 input,
1169 Spanned::from(Tydent::Array(Box::new(elem_ty), array_len)),
1170 ))
1171}
1172
1173fn array_len(input: &str) -> NomResult<&str, u64> {
1175 nom::character::complete::u64(input)
1176}
1177
1178fn tydent_empty_tuple(input: &str) -> NomResult<&str, Spanned<Tydent>> {
1180 let (input, _tup) = tag("()")(input)?;
1181 Ok((input, Spanned::from(Tydent::Empty)))
1182}
1183
1184fn tydent_named(input: &str) -> NomResult<&str, Spanned<Tydent>> {
1186 let (input, (ty_name, generics)) = pair(
1187 ident,
1188 opt(delimited(
1189 pair(unicode_space, tag("<")),
1190 cut(separated_list1(
1191 tag(","),
1192 delimited(unicode_space, tydent_ref, unicode_space),
1193 )),
1194 tag(">"),
1195 )),
1196 )(input)?;
1197
1198 if let Some(_generics) = generics {
1199 panic!("generics aren't yet implemented!");
1200 }
1201 Ok((
1202 input,
1203 Spanned::from(Tydent::Name(Ident {
1204 val: Spanned::from(ty_name.to_owned()),
1205 was_blank: false,
1206 })),
1207 ))
1208}
1209
1210fn ident(input: &str) -> NomResult<&str, &str> {
1212 recognize(pair(
1213 alt((alpha1, tag("_"))),
1214 many0_count(alt((alphanumeric1, tag("_")))),
1215 ))(input)
1216}
1217
1218fn unicode_space(input: &str) -> NomResult<&str, &str> {
1220 alt((
1221 tag(" "),
1222 tag("\t"),
1223 tag("\u{FEFF}"), tag("\u{00A0}"),
1225 tag("\u{1680}"),
1226 tag("\u{2000}"),
1227 tag("\u{2001}"),
1228 tag("\u{2002}"),
1229 tag("\u{2003}"),
1230 tag("\u{2004}"),
1231 tag("\u{2005}"),
1232 tag("\u{2006}"),
1233 tag("\u{2007}"),
1234 tag("\u{2008}"),
1235 tag("\u{2009}"),
1236 tag("\u{200A}"),
1237 tag("\u{202F}"),
1238 tag("\u{205F}"),
1239 tag("\u{3000}"),
1240 ))(input)
1241}
1242
1243#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1254pub struct IntExpr {
1255 pub span: SourceSpan,
1256 pub val: i64,
1257}
1258
1259#[cfg(feature = "eval")]
1262pub use runnable::*;
1263#[cfg(feature = "eval")]
1264mod runnable {
1265 use super::*;
1266
1267 #[derive(Debug, Clone)]
1268 pub enum Stmt {
1269 Let(LetStmt),
1270 Return(ReturnStmt),
1271 Print(PrintStmt),
1272 }
1273
1274 #[derive(Debug, Clone)]
1275 pub struct LetStmt {
1276 pub var: Option<Ident>,
1277 pub expr: Spanned<Expr>,
1278 }
1279
1280 #[derive(Debug, Clone)]
1281 pub struct ReturnStmt {
1282 pub expr: Spanned<Expr>,
1283 }
1284
1285 #[derive(Debug, Clone)]
1286 pub struct PrintStmt {
1287 pub expr: Spanned<Expr>,
1288 }
1289
1290 #[derive(Debug, Clone)]
1291 pub enum Expr {
1292 Call(CallExpr),
1293 Path(PathExpr),
1294 Ctor(CtorExpr),
1295 Literal(LiteralExpr),
1296 }
1297
1298 #[derive(Debug, Clone)]
1299 pub struct CallExpr {
1300 pub func: Ident,
1301 pub args: Vec<Spanned<Expr>>,
1302 }
1303
1304 #[derive(Debug, Clone)]
1305 pub struct PathExpr {
1306 pub var: Ident,
1307 pub path: Vec<Ident>,
1308 }
1309
1310 #[derive(Debug, Clone)]
1311 pub struct CtorExpr {
1312 pub ty: Ident,
1313 pub vals: Vec<Spanned<LetStmt>>,
1314 }
1315
1316 #[derive(Debug, Clone)]
1317 pub struct LiteralExpr {
1318 pub span: SourceSpan,
1319 pub val: Literal,
1320 }
1321
1322 #[derive(Debug, Clone)]
1323 pub enum Literal {
1324 Float(f64),
1325 Int(i64),
1326 Bool(bool),
1327 }
1328
1329 impl Parser<'_> {
1330 pub(crate) fn func_args(
1331 &mut self,
1332 node: &KdlNode,
1333 expr_start: usize,
1334 ) -> Result<Vec<Spanned<Expr>>> {
1335 node.entries()[expr_start..]
1336 .iter()
1337 .enumerate()
1338 .map(|(idx, _e)| self.smol_expr(node, expr_start + idx))
1339 .collect()
1340 }
1341
1342 pub(crate) fn literal_expr(&mut self, entry: &KdlEntry) -> Result<LiteralExpr> {
1343 if entry.name().is_some() {
1344 return Err(KdlScriptParseError {
1345 message: "Named values don't belong here, only literals".to_string(),
1346 src: self.src.clone(),
1347 span: *entry.span(),
1348 help: Some("try removing the name".to_owned()),
1349 })?;
1350 }
1351
1352 let val = match entry.value() {
1353 kdl::KdlValue::RawString(_) | kdl::KdlValue::String(_) => {
1354 return Err(KdlScriptParseError {
1355 message: "strings aren't supported literals".to_string(),
1356 src: self.src.clone(),
1357 span: *entry.span(),
1358 help: None,
1359 })?;
1360 }
1361 kdl::KdlValue::Null => {
1362 return Err(KdlScriptParseError {
1363 message: "nulls aren't supported literals".to_string(),
1364 src: self.src.clone(),
1365 span: *entry.span(),
1366 help: None,
1367 })?;
1368 }
1369 kdl::KdlValue::Base2(int)
1370 | kdl::KdlValue::Base8(int)
1371 | kdl::KdlValue::Base10(int)
1372 | kdl::KdlValue::Base16(int) => Literal::Int(*int),
1373 kdl::KdlValue::Base10Float(val) => Literal::Float(*val),
1374 kdl::KdlValue::Bool(val) => Literal::Bool(*val),
1375 };
1376
1377 Ok(LiteralExpr {
1378 span: *entry.span(),
1379 val,
1380 })
1381 }
1382
1383 pub(crate) fn expr_rhs(
1384 &mut self,
1385 node: &KdlNode,
1386 expr_start: usize,
1387 ) -> Result<Spanned<Expr>> {
1388 trace!("expr rhs");
1389 let expr = if let Ok(string) = self.string_at(node, "", expr_start) {
1390 if let Some((func, "")) = string.rsplit_once(':') {
1391 trace!(" call expr");
1392 let func = Ident::with_span(func.to_owned(), Spanned::span(&string));
1393 let args = self.func_args(node, expr_start + 1)?;
1394 Expr::Call(CallExpr { func, args })
1395 } else if node.children().is_some() {
1396 trace!(" ctor expr");
1397 let ty = Ident::new(string);
1398 let vals = self.let_stmt_children(node)?;
1399 Expr::Ctor(CtorExpr { ty, vals })
1400 } else {
1401 trace!(" path expr");
1402 let mut parts = string.split('.');
1403 let var =
1404 Ident::with_span(parts.next().unwrap().to_owned(), Spanned::span(&string));
1405 let path = parts
1406 .map(|s| Ident::with_span(s.to_owned(), Spanned::span(&string)))
1407 .collect();
1408 Expr::Path(PathExpr { var, path })
1409 }
1410 } else if let Some(val) = node.entries().get(expr_start) {
1411 trace!(" literal expr");
1412 Expr::Literal(self.literal_expr(val)?)
1413 } else {
1414 return Err(KdlScriptParseError {
1415 message: "I thought there was supposed to be an expression after here?"
1416 .to_string(),
1417 src: self.src.clone(),
1418 span: *node.span(),
1419 help: None,
1420 })?;
1421 };
1422
1423 Ok(Spanned::new(expr, *node.span()))
1424 }
1425
1426 pub(crate) fn smol_expr(
1427 &mut self,
1428 node: &KdlNode,
1429 expr_at: usize,
1430 ) -> Result<Spanned<Expr>> {
1431 trace!("smol expr");
1432 let expr = if let Ok(string) = self.string_at(node, "", expr_at) {
1433 if let Some((_func, "")) = string.rsplit_once(':') {
1434 return Err(KdlScriptParseError {
1435 message:
1436 "Nested function calls aren't supported because this is a shitpost"
1437 .to_string(),
1438 src: self.src.clone(),
1439 span: *node.span(),
1440 help: None,
1441 })?;
1442 } else if node.children().is_some() {
1443 return Err(KdlScriptParseError {
1444 message: "Ctors exprs can't be nested in function calls because this is a shitpost".to_string(),
1445 src: self.src.clone(),
1446 span: *node.span(),
1447 help: None,
1448 })?;
1449 } else {
1450 trace!(" path expr");
1451 let mut parts = string.split('.');
1452 let var =
1453 Ident::with_span(parts.next().unwrap().to_owned(), Spanned::span(&string));
1454 let path = parts
1455 .map(|s| Ident::with_span(s.to_owned(), Spanned::span(&string)))
1456 .collect();
1457 Expr::Path(PathExpr { var, path })
1458 }
1459 } else if let Some(val) = node.entries().get(expr_at) {
1460 trace!(" literal expr");
1461 Expr::Literal(self.literal_expr(val)?)
1462 } else {
1463 return Err(KdlScriptParseError {
1464 message: "I thought there was supposed to be an expression after here?"
1465 .to_string(),
1466 src: self.src.clone(),
1467 span: *node.span(),
1468 help: None,
1469 })?;
1470 };
1471
1472 Ok(Spanned::new(expr, *node.span()))
1473 }
1474
1475 pub(crate) fn let_stmt_children(
1476 &mut self,
1477 node: &KdlNode,
1478 ) -> Result<Vec<Spanned<LetStmt>>> {
1479 node.children()
1480 .into_iter()
1481 .flat_map(|d| d.nodes())
1482 .map(|var| {
1483 let name = self.var_name_decl(var)?;
1484 let expr = self.expr_rhs(var, 0)?;
1485 Ok(Spanned::new(LetStmt { var: name, expr }, *var.span()))
1486 })
1487 .collect()
1488 }
1489 }
1490
1491 impl ParsedProgram {
1492 pub(crate) fn add_builtin_funcs(&mut self) -> Result<()> {
1493 self.funcs.insert(
1495 Ident::from(String::from("+")),
1496 FuncDecl {
1497 name: Ident::from(String::from("+")),
1498 inputs: vec![
1499 TypedVar {
1500 name: Some(Ident::from(String::from("lhs"))),
1501 ty: Spanned::from(Tydent::Name(Ident::from(String::from("i64")))),
1502 },
1503 TypedVar {
1504 name: Some(Ident::from(String::from("rhs"))),
1505 ty: Spanned::from(Tydent::Name(Ident::from(String::from("i64")))),
1506 },
1507 ],
1508 outputs: vec![TypedVar {
1509 name: Some(Ident::from(String::from("out"))),
1510 ty: Spanned::from(Tydent::Name(Ident::from(String::from("i64")))),
1511 }],
1512 attrs: vec![],
1513
1514 body: vec![],
1515 },
1516 );
1517
1518 Ok(())
1519 }
1520 }
1521}