kaiju_core/
program.rs

1use crate::ast::*;
2use crate::error::*;
3use crate::parser::*;
4use serde_json;
5use std::collections::HashMap;
6
7const VERSION: u8 = 1;
8const MAGIC_PROGRAM: [u8; 4] = [0x4b, 0x4a, 0x50, VERSION];
9const MAGIC_MODULE: [u8; 4] = [0x4b, 0x4a, 0x4d, VERSION];
10
11#[inline]
12pub fn compile_module(source: &str) -> CompilationResult<Module> {
13    Module::from_ast(&parse_module(source)?)
14}
15
16#[inline]
17pub fn compile_ops_descriptor(source: &str) -> CompilationResult<OpsDescriptor> {
18    OpsDescriptor::from_ast(&parse_ops_descriptor(source)?)
19}
20
21fn convert_ast_meta(ast: &[AstMeta]) -> CompilationResult<Vec<Meta>> {
22    let mut result = vec![];
23    for m in ast {
24        for field in &m.0 {
25            result.push(Meta::from_ast(&field)?);
26        }
27    }
28    Ok(result)
29}
30
31fn convert_ast_op_definition(ast: &[AstOpRuleDef]) -> CompilationResult<OpDefinition> {
32    let mut result = HashMap::new();
33    for def in ast {
34        let mut r = HashMap::new();
35        for desc in &def.description {
36            r.insert(desc.id.0.clone(), desc.value.0.clone());
37        }
38        result.insert(def.id.0.clone(), r);
39    }
40    Ok(result)
41}
42
43#[derive(Debug, Serialize, Deserialize, Clone)]
44pub struct Program {
45    pub magic: [u8; 4],
46    pub entry: Option<Entry>,
47    pub modules: Vec<Module>,
48}
49
50impl Program {
51    pub fn from_modules(entry: Option<Entry>, modules: Vec<Module>) -> SimpleResult<Self> {
52        if let Some(ref entry) = entry {
53            if entry.module >= modules.len() {
54                return Err(SimpleError::new(format!(
55                    "Entry module index: {} out of bounds: {}",
56                    entry.module,
57                    modules.len()
58                )));
59            }
60            if entry.function >= modules[entry.module].functions.len() {
61                return Err(SimpleError::new(format!(
62                    "Entry function index: {} out of bounds: {}",
63                    entry.function,
64                    modules[entry.module].functions.len()
65                )));
66            }
67        }
68        Ok(Self {
69            magic: MAGIC_PROGRAM,
70            modules,
71            entry,
72        })
73    }
74
75    pub fn from_json(source: &str) -> serde_json::Result<Self> {
76        serde_json::from_str(source)
77    }
78
79    pub fn to_json(&self, pretty: bool) -> serde_json::Result<String> {
80        if pretty {
81            serde_json::to_string_pretty(self)
82        } else {
83            serde_json::to_string(self)
84        }
85    }
86
87    pub fn modules_map(&self) -> Vec<(usize, String)> {
88        self.modules
89            .iter()
90            .enumerate()
91            .map(|(i, m)| (i, m.path.clone()))
92            .collect()
93    }
94
95    pub fn find_module(&self, path: &str) -> Option<&Module> {
96        self.modules.iter().find(|m| m.path == path)
97    }
98
99    pub fn find_module_struct(&self, path: &str, id: &str) -> Option<&Struct> {
100        self.find_module(path)?.find_struct(id)
101    }
102
103    pub fn find_struct(&self, id: &str) -> Option<&Struct> {
104        for m in &self.modules {
105            for s in &m.structs {
106                if s.id == id {
107                    return Some(s);
108                }
109            }
110        }
111        None
112    }
113}
114
115#[derive(Debug, Serialize, Deserialize, Clone)]
116pub struct Entry {
117    pub module: usize,
118    pub function: usize,
119}
120
121impl Entry {
122    #[inline]
123    pub fn new(module: usize, function: usize) -> Self {
124        Self { module, function }
125    }
126}
127
128#[derive(Debug, Serialize, Deserialize, Clone)]
129pub struct Module {
130    pub magic: [u8; 4],
131    pub shebang: Option<String>,
132    pub path: String,
133    pub meta: Vec<Meta>,
134    pub imports: Vec<Import>,
135    pub globals: Vec<Variable>,
136    pub externs: Vec<Extern>,
137    pub structs: Vec<Struct>,
138    pub functions: Vec<Function>,
139}
140
141impl Module {
142    pub fn from_ast(ast: &AstModule) -> CompilationResult<Self> {
143        let mut meta = vec![];
144        let mut imports = vec![];
145        let mut globals = vec![];
146        let mut externs = vec![];
147        let mut structs = vec![];
148        let mut functions = vec![];
149        for instruction in &ast.instructions {
150            match instruction {
151                AstInstruction::Meta(m) => meta.extend(
152                    m.0.iter()
153                        .map(|m| Meta::from_ast(m))
154                        .collect::<CompilationResult<Vec<Meta>>>()?,
155                ),
156                AstInstruction::Import(i) => imports.push(Import::from_ast(i)?),
157                AstInstruction::Globals(g) => globals.extend(
158                    g.iter()
159                        .map(|v| Variable::from_ast(v))
160                        .collect::<CompilationResult<Vec<Variable>>>()?,
161                ),
162                AstInstruction::Extern(e) => externs.push(Extern::from_ast(e)?),
163                AstInstruction::Struct(s) => structs.push(Struct::from_ast(s)?),
164                AstInstruction::Function(f) => functions.push(Function::from_ast(f)?),
165            }
166        }
167        Ok(Self {
168            magic: MAGIC_MODULE,
169            shebang: if let Some(ref shebang) = ast.shebang {
170                Some(shebang.clone())
171            } else {
172                None
173            },
174            path: "".to_owned(),
175            meta,
176            imports,
177            globals,
178            externs,
179            structs,
180            functions,
181        })
182    }
183
184    #[inline]
185    pub fn from_json(source: &str) -> serde_json::Result<Self> {
186        serde_json::from_str(source)
187    }
188
189    #[inline]
190    pub fn to_json(&self, pretty: bool) -> serde_json::Result<String> {
191        if pretty {
192            serde_json::to_string_pretty(self)
193        } else {
194            serde_json::to_string(self)
195        }
196    }
197
198    pub fn globals_map(&self) -> Vec<(usize, String)> {
199        self.structs
200            .iter()
201            .enumerate()
202            .map(|(i, g)| (i, g.id.clone()))
203            .collect()
204    }
205
206    pub fn externs_map(&self) -> Vec<(usize, String)> {
207        self.externs
208            .iter()
209            .enumerate()
210            .map(|(i, e)| (i, e.item.id.clone()))
211            .collect()
212    }
213
214    pub fn structs_map(&self) -> Vec<(usize, String)> {
215        self.structs
216            .iter()
217            .enumerate()
218            .map(|(i, s)| (i, s.id.clone()))
219            .collect()
220    }
221
222    pub fn functions_map(&self) -> Vec<(usize, String)> {
223        self.functions
224            .iter()
225            .enumerate()
226            .map(|(i, f)| (i, f.header.id.clone()))
227            .collect()
228    }
229
230    #[inline]
231    pub fn find_struct(&self, id: &str) -> Option<&Struct> {
232        self.structs.iter().find(|s| s.id == id)
233    }
234
235    #[inline]
236    pub fn find_function(&self, id: &str) -> Option<&Function> {
237        self.functions.iter().find(|f| f.header.id == id)
238    }
239}
240
241#[derive(Debug, Serialize, Deserialize, Clone)]
242pub struct Meta {
243    pub id: String,
244    pub args: Vec<MetaValue>,
245}
246
247impl Meta {
248    pub fn from_ast(ast: &AstMetaField) -> CompilationResult<Self> {
249        Ok(Self {
250            id: ast.id.0.clone(),
251            args: ast
252                .args
253                .iter()
254                .map(|v| MetaValue::from_ast(v))
255                .collect::<CompilationResult<Vec<MetaValue>>>()?,
256        })
257    }
258}
259
260#[derive(Debug, Serialize, Deserialize, Clone)]
261pub enum MetaValue {
262    Named(String, Box<MetaValue>),
263    Field(Meta),
264    String(String),
265    Number(Number),
266}
267
268impl MetaValue {
269    pub fn from_ast(ast: &AstMetaValue) -> CompilationResult<Self> {
270        Ok(match ast {
271            AstMetaValue::Named(n, v) => {
272                MetaValue::Named(n.0.clone(), Box::new(MetaValue::from_ast(v)?))
273            }
274            AstMetaValue::Field(v) => MetaValue::Field(Meta::from_ast(v)?),
275            AstMetaValue::String(v) => MetaValue::String(v.0.clone()),
276            AstMetaValue::Number(v) => MetaValue::Number(Number::from_ast(v)?),
277        })
278    }
279}
280
281#[derive(Debug, Serialize, Deserialize, Clone)]
282pub struct Import {
283    pub meta: Vec<Meta>,
284    pub names: Vec<String>,
285    pub module: String,
286}
287
288impl Import {
289    pub fn from_ast(ast: &AstImport) -> CompilationResult<Self> {
290        Ok(Self {
291            meta: convert_ast_meta(&ast.meta)?,
292            names: ast.names.iter().map(|n| n.0.clone()).collect(),
293            module: ast.module.0.clone(),
294        })
295    }
296}
297
298#[derive(Debug, Serialize, Deserialize, Clone)]
299pub struct Extern {
300    pub meta: Vec<Meta>,
301    pub item: FunctionHeader,
302    pub location_module: String,
303    pub location_function: String,
304}
305
306impl Extern {
307    pub fn from_ast(ast: &AstExtern) -> CompilationResult<Self> {
308        Ok(Self {
309            meta: convert_ast_meta(&ast.meta)?,
310            item: FunctionHeader::from_ast(&ast.item)?,
311            location_module: ast.location_module.0.clone(),
312            location_function: ast.location_function.0.clone(),
313        })
314    }
315}
316
317#[derive(Debug, Serialize, Deserialize, Clone)]
318pub struct Variable {
319    pub id: String,
320    pub typeid: Type,
321}
322
323impl Variable {
324    pub fn from_ast(ast: &AstVariable) -> CompilationResult<Self> {
325        Ok(Self {
326            id: ast.id.0.clone(),
327            typeid: Type::from_ast(&ast.typeid)?,
328        })
329    }
330}
331
332impl ToString for Variable {
333    fn to_string(&self) -> String {
334        format!("{}:{}", self.id, self.typeid.to_string())
335    }
336}
337
338#[derive(Debug, Serialize, Deserialize, Clone)]
339pub enum Type {
340    Identifier(String),
341    Pointer(Box<Type>),
342    Tuple(Vec<Type>),
343}
344
345impl Type {
346    pub fn from_ast(ast: &AstType) -> CompilationResult<Self> {
347        Ok(match ast {
348            AstType::Identifier(v) => Type::Identifier(v.0.clone()),
349            AstType::Pointer(v) => Type::Pointer(Box::new(Type::from_ast(v)?)),
350            AstType::Tuple(v) => Type::Tuple(
351                v.iter()
352                    .map(|v| Type::from_ast(v))
353                    .collect::<CompilationResult<Vec<Type>>>()?,
354            ),
355        })
356    }
357
358    pub fn as_identifier(&self) -> Option<&str> {
359        match self {
360            Type::Identifier(ref i) => Some(i),
361            _ => None,
362        }
363    }
364
365    pub fn as_pointer(&self) -> Option<&Type> {
366        match self {
367            Type::Pointer(ref t) => Some(t.as_ref()),
368            _ => None,
369        }
370    }
371
372    pub fn as_tuple(&self) -> Option<&[Type]> {
373        match self {
374            Type::Tuple(ref t) => Some(t),
375            _ => None,
376        }
377    }
378}
379
380impl ToString for Type {
381    fn to_string(&self) -> String {
382        match self {
383            Type::Identifier(t) => t.clone(),
384            Type::Pointer(t) => format!("*{}", t.to_string()),
385            Type::Tuple(t) => format!(
386                "({})",
387                t.iter()
388                    .map(|t| t.to_string())
389                    .collect::<Vec<String>>()
390                    .join(", ")
391            ),
392        }
393    }
394}
395
396impl Default for Type {
397    fn default() -> Self {
398        Type::Identifier("".to_owned())
399    }
400}
401
402impl PartialEq for Type {
403    fn eq(&self, other: &Self) -> bool {
404        match self {
405            Type::Identifier(ts) => {
406                ts == "?"
407                    || match other {
408                        Type::Identifier(to) => to == "?" || ts == to,
409                        _ => false,
410                    }
411            }
412            Type::Pointer(ts) => match other {
413                Type::Identifier(to) => to == "?",
414                Type::Pointer(to) => ts == to,
415                _ => false,
416            },
417            Type::Tuple(ts) => match other {
418                Type::Identifier(to) => to == "?",
419                Type::Tuple(to) => ts == to,
420                _ => false,
421            },
422        }
423    }
424}
425
426#[derive(Debug, Serialize, Deserialize, Clone)]
427pub struct Struct {
428    pub meta: Vec<Meta>,
429    pub export: bool,
430    pub id: String,
431    pub fields: Vec<Variable>,
432}
433
434impl Struct {
435    pub fn from_ast(ast: &AstStruct) -> CompilationResult<Self> {
436        Ok(Self {
437            meta: convert_ast_meta(&ast.meta)?,
438            export: ast.export,
439            id: ast.id.0.clone(),
440            fields: ast
441                .fields
442                .iter()
443                .map(|v| Variable::from_ast(v))
444                .collect::<CompilationResult<Vec<Variable>>>()?,
445        })
446    }
447}
448
449#[derive(Debug, Serialize, Deserialize, Clone)]
450pub struct Function {
451    pub meta: Vec<Meta>,
452    pub export: bool,
453    pub header: FunctionHeader,
454    pub locals: Vec<Variable>,
455    pub body: Vec<BlockOp>,
456}
457
458impl Function {
459    pub fn from_ast(ast: &AstFunction) -> CompilationResult<Self> {
460        Ok(Self {
461            meta: convert_ast_meta(&ast.meta)?,
462            export: ast.export,
463            header: FunctionHeader::from_ast(&ast.header)?,
464            locals: ast
465                .locals
466                .iter()
467                .map(|v| Variable::from_ast(v))
468                .collect::<CompilationResult<Vec<Variable>>>()?,
469            body: ast
470                .ops
471                .iter()
472                .map(|o| BlockOp::from_ast(o))
473                .collect::<CompilationResult<Vec<BlockOp>>>()?,
474        })
475    }
476}
477
478#[derive(Debug, Serialize, Deserialize, Clone)]
479pub struct FunctionHeader {
480    pub id: String,
481    pub params: Vec<Variable>,
482    pub typeid: Option<Type>,
483}
484
485impl FunctionHeader {
486    pub fn from_ast(ast: &AstFunctionHeader) -> CompilationResult<Self> {
487        Ok(Self {
488            id: ast.id.0.clone(),
489            params: ast
490                .params
491                .iter()
492                .map(|v| Variable::from_ast(v))
493                .collect::<CompilationResult<Vec<Variable>>>()?,
494            typeid: if let Some(ref t) = ast.typeid {
495                Some(Type::from_ast(&t)?)
496            } else {
497                None
498            },
499        })
500    }
501}
502
503impl ToString for FunctionHeader {
504    fn to_string(&self) -> String {
505        let id = self.id.clone();
506        let params = self
507            .params
508            .iter()
509            .map(|p| p.to_string())
510            .collect::<Vec<String>>()
511            .join(", ");
512        let typeid = if let Some(ref t) = self.typeid {
513            t.to_string()
514        } else {
515            "".to_owned()
516        };
517        format!("fn {}({}){}", id, params, typeid)
518    }
519}
520
521#[derive(Debug, Serialize, Deserialize, Clone)]
522pub enum BlockOp {
523    Label(String),
524    Operation(Operation),
525}
526
527impl BlockOp {
528    pub fn from_ast(ast: &AstBlockOp) -> CompilationResult<Self> {
529        Ok(match ast {
530            AstBlockOp::Label(l) => BlockOp::Label(l.0.clone()),
531            AstBlockOp::Operation(o) => BlockOp::Operation(Operation::from_ast(o)?),
532        })
533    }
534
535    pub fn is_operation(&self) -> bool {
536        match self {
537            BlockOp::Operation(_) => true,
538            _ => false,
539        }
540    }
541
542    pub fn as_label(&self) -> Option<&String> {
543        match self {
544            BlockOp::Label(ref v) => Some(v),
545            _ => None,
546        }
547    }
548
549    pub fn as_operation(&self) -> Option<&Operation> {
550        match self {
551            BlockOp::Operation(ref v) => Some(v),
552            _ => None,
553        }
554    }
555}
556
557#[derive(Debug, Serialize, Deserialize, Clone)]
558pub struct Operation {
559    pub meta: Vec<Meta>,
560    pub id: String,
561    pub params: Vec<Value>,
562    pub targets: Vec<Value>,
563}
564
565impl Operation {
566    pub fn from_ast(ast: &AstOperation) -> CompilationResult<Self> {
567        Ok(Self {
568            meta: convert_ast_meta(&ast.meta)?,
569            id: ast.id.0.clone(),
570            params: ast
571                .params
572                .iter()
573                .map(|v| Value::from_ast(v))
574                .collect::<CompilationResult<Vec<Value>>>()?,
575            targets: ast
576                .targets
577                .iter()
578                .map(|t| Value::from_ast(t))
579                .collect::<CompilationResult<Vec<Value>>>()?,
580        })
581    }
582}
583
584#[derive(Debug, Serialize, Deserialize, Clone)]
585pub enum Value {
586    Ref(Box<Value>, Option<Box<Access>>),
587    Deref(Box<Value>, Option<Box<Access>>),
588    FunctionCall(String, Vec<Value>, Option<Box<Access>>),
589    Tuple(Vec<Value>, Option<Box<Access>>),
590    String(String, Type),
591    Number(Number),
592    OperationInline(String, Vec<Value>, Option<Box<Access>>),
593    Variable(String, Option<Box<Access>>),
594}
595
596impl Value {
597    pub fn from_ast(ast: &AstValue) -> CompilationResult<Self> {
598        Ok(match ast {
599            AstValue::Ref(v, a) => Value::Ref(
600                Box::new(Value::from_ast(v)?),
601                if let Some(a) = a {
602                    Some(Box::new(Access::from_ast(a)?))
603                } else {
604                    None
605                },
606            ),
607            AstValue::Deref(v, a) => Value::Deref(
608                Box::new(Value::from_ast(v)?),
609                if let Some(a) = a {
610                    Some(Box::new(Access::from_ast(a)?))
611                } else {
612                    None
613                },
614            ),
615            AstValue::FunctionCall(i, v, a) => Value::FunctionCall(
616                i.0.clone(),
617                v.iter()
618                    .map(|v| Value::from_ast(v))
619                    .collect::<CompilationResult<Vec<Value>>>()?,
620                if let Some(a) = a {
621                    Some(Box::new(Access::from_ast(a)?))
622                } else {
623                    None
624                },
625            ),
626            AstValue::Tuple(v, a) => Value::Tuple(
627                v.iter()
628                    .map(|v| Value::from_ast(v))
629                    .collect::<CompilationResult<Vec<Value>>>()?,
630                if let Some(a) = a {
631                    Some(Box::new(Access::from_ast(a)?))
632                } else {
633                    None
634                },
635            ),
636            AstValue::String(v) => Value::String(v.0.clone(), Type::from_ast(&v.1)?),
637            AstValue::Number(v) => Value::Number(Number::from_ast(v)?),
638            AstValue::OperationInline(i, v, a) => Value::OperationInline(
639                i.0.clone(),
640                v.iter()
641                    .map(|v| Value::from_ast(v))
642                    .collect::<CompilationResult<Vec<Value>>>()?,
643                if let Some(a) = a {
644                    Some(Box::new(Access::from_ast(a)?))
645                } else {
646                    None
647                },
648            ),
649            AstValue::Variable(v, a) => Value::Variable(
650                v.0.clone(),
651                if let Some(a) = a {
652                    Some(Box::new(Access::from_ast(a)?))
653                } else {
654                    None
655                },
656            ),
657        })
658    }
659}
660
661#[derive(Debug, Serialize, Deserialize, Clone)]
662pub enum Access {
663    Tuple(i64, Option<Box<Access>>),
664    Variable(String, Option<Box<Access>>),
665}
666
667impl Access {
668    pub fn from_ast(ast: &AstAccess) -> CompilationResult<Self> {
669        Ok(match ast {
670            AstAccess::Variable(v, a) => Access::Variable(
671                v.0.clone(),
672                if let Some(a) = a {
673                    Some(Box::new(Access::from_ast(a)?))
674                } else {
675                    None
676                },
677            ),
678            AstAccess::Tuple(v, a) => Access::Tuple(
679                v.0,
680                if let Some(a) = a {
681                    Some(Box::new(Access::from_ast(a)?))
682                } else {
683                    None
684                },
685            ),
686        })
687    }
688}
689
690#[derive(Debug, Serialize, Deserialize, Clone)]
691pub enum Number {
692    Integer(i64, Type),
693    Float(f64, Type),
694}
695
696impl Number {
697    pub fn from_ast(ast: &AstNumber) -> CompilationResult<Self> {
698        Ok(match ast {
699            AstNumber::Integer(v) => Number::Integer(v.0, Type::from_ast(&v.1)?),
700            AstNumber::Float(v) => Number::Float(v.0, Type::from_ast(&v.1)?),
701        })
702    }
703}
704
705#[derive(Debug, Serialize, Deserialize, Clone, Default)]
706pub struct OpsDescriptor {
707    pub meta: Vec<Meta>,
708    pub rules: Vec<OpRule>,
709}
710
711impl OpsDescriptor {
712    pub fn from_ast(ast: &AstOpsDescriptor) -> CompilationResult<Self> {
713        Ok(OpsDescriptor {
714            meta: convert_ast_meta(&ast.meta)?,
715            rules: ast
716                .rules
717                .iter()
718                .map(|r| OpRule::from_ast(r))
719                .collect::<CompilationResult<Vec<OpRule>>>()?,
720        })
721    }
722
723    pub fn merge(descriptors: &[OpsDescriptor]) -> Self {
724        OpsDescriptor {
725            meta: descriptors.iter().flat_map(|d| d.meta.clone()).collect(),
726            rules: descriptors.iter().flat_map(|d| d.rules.clone()).collect(),
727        }
728    }
729}
730
731#[derive(Debug, Serialize, Deserialize, Clone)]
732pub struct OpRule {
733    pub meta: Vec<Meta>,
734    pub id: String,
735    pub params: Vec<OpParam>,
736    pub targets: Vec<Type>,
737    pub definition: OpDefinition,
738}
739
740impl OpRule {
741    pub fn from_ast(ast: &AstOpRule) -> CompilationResult<Self> {
742        Ok(OpRule {
743            meta: convert_ast_meta(&ast.meta)?,
744            id: ast.id.0.clone(),
745            params: ast
746                .params
747                .iter()
748                .map(|p| OpParam::from_ast(p))
749                .collect::<CompilationResult<Vec<OpParam>>>()?,
750            targets: ast
751                .targets
752                .iter()
753                .map(|t| Type::from_ast(t))
754                .collect::<Result<Vec<Type>, CompilationError>>()?,
755            definition: convert_ast_op_definition(&ast.definition)?,
756        })
757    }
758}
759
760#[derive(Debug, Serialize, Deserialize, Clone)]
761pub struct OpParam {
762    pub id: String,
763    pub typeid: Type,
764}
765
766impl OpParam {
767    pub fn from_ast(ast: &AstOpParam) -> CompilationResult<Self> {
768        Ok(OpParam {
769            id: ast.id.0.clone(),
770            typeid: Type::from_ast(&ast.typeid)?,
771        })
772    }
773}
774
775pub type OpDefinition = HashMap<String, HashMap<String, String>>;