1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::{
    helpers::{IntoWasm, WasmInstruction},
    operations::Operation,
    symbols::WasmExportName,
    types::WasmType,
    WasmSymbol,
};
use indexmap::IndexMap;
use nyar_error::FileSpan;
use std::{collections::BTreeMap, slice::Iter};
use wast::{
    component::{
        CanonLift, CanonLower, ComponentFunctionParam, ComponentFunctionResult, ComponentFunctionType, ComponentTypeUse,
        CoreFunc, CoreFuncKind, Func, FuncKind, Start,
    },
    core::{Expression, TypeUse, ValType},
    token::{Id, NameAnnotation, Span},
};
pub mod codegen;

/// `function`
pub struct FunctionType {
    pub symbol: WasmSymbol,
    pub export: WasmExportName,
    pub entry: bool,
    pub input: IndexMap<String, ParameterType>,
    pub local: BTreeMap<String, ParameterType>,
    pub output: Vec<WasmType>,
    pub body: FunctionBody,
    pub span: FileSpan,
}

pub struct ParameterType {
    pub name: WasmSymbol,
    pub type_hint: WasmType,
    pub span: FileSpan,
}

impl ParameterType {
    pub fn new<S>(name: S) -> Self
    where
        S: Into<WasmSymbol>,
    {
        Self { name: name.into(), type_hint: WasmType::Any { nullable: true }, span: Default::default() }
    }
    pub fn with_type(self, type_hint: WasmType) -> Self {
        Self { type_hint, ..self }
    }
}

impl FunctionType {
    pub fn new<S: Into<WasmSymbol>>(name: S) -> Self {
        Self {
            symbol: name.into(),
            export: WasmExportName::default(),
            entry: false,
            input: IndexMap::default(),
            local: BTreeMap::default(),
            output: vec![],
            body: FunctionBody::default(),
            span: Default::default(),
        }
    }
    pub fn name(&self) -> String {
        self.symbol.to_string()
    }
    pub fn with_export(self, export: bool) -> Self {
        Self { export: WasmExportName::create_by(&self.symbol, export), ..self }
    }
    pub fn with_entry(self, entry: bool) -> Self {
        Self { entry, ..self }
    }
    pub fn with_inputs<I>(mut self, inputs: I) -> Self
    where
        I: IntoIterator<Item = ParameterType>,
    {
        for i in inputs {
            self.input.insert(i.name.to_string(), i);
        }
        self
    }
    pub fn with_outputs<I>(mut self, outputs: I) -> Self
    where
        I: IntoIterator<Item = WasmType>,
    {
        self.output.extend(outputs);
        self
    }
    pub fn with_locals<I>(mut self, locals: I) -> Self
    where
        I: IntoIterator<Item = ParameterType>,
    {
        for i in locals {
            self.local.insert(i.name.to_string(), i);
        }
        self
    }
    pub fn with_operations<I>(mut self, operations: I) -> Self
    where
        I: IntoIterator<Item = Operation>,
    {
        self.body.codes.extend(operations);
        self
    }
}

#[derive(Default)]
pub struct FunctionBody {
    codes: Vec<Operation>,
}

impl<'i> IntoIterator for &'i FunctionBody {
    type Item = &'i Operation;
    type IntoIter = Iter<'i, Operation>;

    fn into_iter(self) -> Self::IntoIter {
        self.codes.iter()
    }
}