1#![allow(dead_code)]
2use super::codegen::CodeGen;
3use super::emit::{CallStyle, Emitter};
4use super::interface::IfaceMapping;
5use super::package::PkgVarPairs;
6use super::types::TypeCache;
7use goscript_parser::ast::Ident;
8use goscript_parser::errors::ErrorList;
9use goscript_parser::objects::Objects as AstObjects;
10use goscript_parser::objects::*;
11use goscript_parser::FileSet;
12use goscript_types::{Config, PackageKey as TCPackageKey, TCObjects, TypeInfo};
13use goscript_vm::gc::GcoVec;
14use goscript_vm::instruction::*;
15use goscript_vm::null_key;
16use goscript_vm::value::*;
17use goscript_vm::vm::ByteCode;
18use std::collections::HashMap;
19use std::pin::Pin;
20
21pub struct EntryGen<'a> {
22 objects: Pin<Box<VMObjects>>,
23 ast_objs: &'a AstObjects,
24 tc_objs: &'a TCObjects,
25 dummy_gcv: GcoVec,
26 packages: Vec<PackageKey>,
27 iface_mapping: IfaceMapping,
28 pkg_indices: HashMap<TCPackageKey, OpIndex>,
30 blank_ident: IdentKey,
31}
32
33impl<'a> EntryGen<'a> {
34 pub fn new(asto: &'a AstObjects, tco: &'a TCObjects, bk: IdentKey) -> EntryGen<'a> {
35 EntryGen {
36 objects: Box::pin(VMObjects::new()),
37 ast_objs: asto,
38 tc_objs: tco,
39 dummy_gcv: GcoVec::new(),
40 packages: Vec::new(),
41 iface_mapping: IfaceMapping::new(),
42 pkg_indices: HashMap::new(),
43 blank_ident: bk,
44 }
45 }
46
47 fn gen_entry_func(
49 &mut self,
50 pkg: PackageKey,
51 index: OpIndex,
52 main_ident: IdentKey,
53 pairs: &mut PkgVarPairs,
54 ) -> FunctionKey {
55 let fmeta = self.objects.metadata.default_sig;
57 let f = GosValue::new_function(
58 null_key!(),
59 fmeta.clone(),
60 &mut self.objects,
61 &self.dummy_gcv,
62 FuncFlag::Default,
63 );
64 let fkey = *f.as_function();
65 let func = &mut self.objects.functions[fkey];
66 let mut emitter = Emitter::new(func);
67 emitter.emit_import(index, pkg, None);
68 emitter.emit_load(
69 EntIndex::PackageMember(pkg, main_ident),
70 Some((pairs, fkey)),
71 ValueType::Function,
72 None,
73 );
74 emitter.emit_pre_call(None);
75 emitter.emit_call(CallStyle::Default, false, None);
76 emitter.emit_return(None, None);
77 *f.as_function()
78 }
79
80 pub fn gen(
81 mut self,
82 checker_result: &HashMap<TCPackageKey, TypeInfo>,
83 main_pkg: TCPackageKey,
84 main_ident: IdentKey,
85 ) -> ByteCode {
86 let mut main_pkg_idx = None;
87 for (&tcpkg, _) in checker_result.iter() {
88 let name = self.tc_objs.pkgs[tcpkg].name().clone().unwrap();
90 let pkey = self.objects.packages.insert(PackageVal::new(name));
91 self.packages.push(pkey);
92 let index = (self.packages.len() - 1) as OpIndex;
93 self.pkg_indices.insert(tcpkg, index);
94 if tcpkg == main_pkg {
95 main_pkg_idx = Some(index);
96 }
97 }
98 let mut type_cache: TypeCache = HashMap::new();
99 let mut pairs = PkgVarPairs::new();
100 for (i, (tcpkg, ti)) in checker_result.iter().enumerate() {
101 let mut cgen = CodeGen::new(
102 &mut self.objects,
103 self.ast_objs,
104 self.tc_objs,
105 &mut self.dummy_gcv,
106 &ti,
107 &mut type_cache,
108 &mut self.iface_mapping,
109 &self.pkg_indices,
110 &self.packages,
111 self.packages[i],
112 self.blank_ident,
113 );
114 cgen.gen_with_files(&ti.ast_files, *tcpkg, i as OpIndex);
115 pairs.append_from_util(cgen.pkg_util());
116 }
117 let index = main_pkg_idx.unwrap();
118 let entry =
119 self.gen_entry_func(self.packages[index as usize], index, main_ident, &mut pairs);
120 pairs.patch_index(self.ast_objs, &mut self.objects);
121 ByteCode {
122 objects: self.objects,
123 packages: self.packages,
124 ifaces: self.iface_mapping.into_result(),
125 entry: entry,
126 }
127 }
128}
129
130pub fn parse_check_gen(
131 path: &str,
132 config: &Config,
133 fset: &mut FileSet,
134 el: &ErrorList,
135) -> Result<ByteCode, usize> {
136 let asto = &mut AstObjects::new();
137 let tco = &mut goscript_types::TCObjects::new();
138 let results = &mut HashMap::new();
139 let pkgs = &mut HashMap::new();
140
141 let importer =
142 &mut goscript_types::Importer::new(&config, fset, pkgs, results, asto, tco, el, 0);
143 let key = goscript_types::ImportKey::new(path, "./");
144 let main_pkg = importer.import(&key);
145
146 if el.len() > 0 {
147 Err(el.len())
148 } else {
149 let blank_ident = asto.idents.insert(Ident::blank(0));
150 let main_ident = asto.idents.insert(Ident::with_str(0, "main"));
151 let gen = EntryGen::new(asto, tco, blank_ident);
152 Ok(gen.gen(results, main_pkg.unwrap(), main_ident))
153 }
154}