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>>;