1use std::{convert::TryFrom, vec};
6
7use thiserror::Error;
8
9use crate::utils::Join;
10
11use super::{
12 analyzer::{Function, GlobalNameInfo, UpvalueNameInfo},
13 ast::*,
14 code::{Code, ConstValue, FunctionKind},
15 opcode::{JumpTarget, OpCode},
16 parser::ParserError,
17};
18
19impl TryFrom<BinOp> for OpCode {
20 type Error = SyntaxError;
21
22 fn try_from(value: BinOp) -> Result<Self, Self::Error> {
23 Ok(match value {
24 BinOp::Add => OpCode::Add,
25 BinOp::Sub => OpCode::Sub,
26 BinOp::Mul => OpCode::Mul,
27 BinOp::Div => OpCode::Div,
28 BinOp::Mod => OpCode::Mod,
29 BinOp::Eq => OpCode::Eq,
30 BinOp::Lt => OpCode::Lt,
31 BinOp::Le => OpCode::Le,
32 BinOp::Ne => OpCode::Ne,
33 BinOp::Ge => OpCode::Ge,
34 BinOp::Gt => OpCode::Gt,
35 BinOp::Is => OpCode::Is,
36 _ => return Err(SyntaxError::IllegalAst),
37 })
38 }
39}
40
41pub fn gen_code(func_list: Vec<Function>) -> Result<Code, SyntaxError> {
43 CodeGen { func_list }.gen_code(0)
44}
45
46struct CodeGen {
47 func_list: Vec<Function>,
48}
49
50impl CodeGen {
51 fn get_jump_target(&mut self, func_id: usize) -> JumpTarget {
52 self.func_list[func_id].jump_target_count += 1;
53 JumpTarget(self.func_list[func_id].jump_target_count - 1)
54 }
55
56 fn add_const(&mut self, func_id: usize, value: ConstValue) -> usize {
57 if let Some(index) = self.func_list[func_id]
58 .consts
59 .iter()
60 .position(|x| *x == value)
61 {
62 index
63 } else {
64 self.func_list[func_id].consts.push(value);
65 self.func_list[func_id].consts.len() - 1
66 }
67 }
68
69 fn load(&mut self, func_id: usize, name: &str) -> Result<(), SyntaxError> {
70 let t = if let Some(i) = self.func_list[func_id].local_names.get_index_of(name) {
71 OpCode::LoadLocal(i)
72 } else if let Some(i) = self.func_list[func_id]
73 .global_names
74 .get_index_of(&GlobalNameInfo::from(name.to_owned()))
75 {
76 OpCode::LoadGlobal(i)
77 } else if let Some(i) = self.func_list[func_id]
78 .upvalue_names
79 .get_index_of(&UpvalueNameInfo::from(name.to_owned()))
80 {
81 OpCode::LoadUpvalue(i)
82 } else {
83 return Err(SyntaxError::IllegalAst);
84 };
85 self.func_list[func_id].code.push(t);
86 Ok(())
87 }
88
89 fn store(&mut self, func_id: usize, name: &str) -> Result<(), SyntaxError> {
90 let t = if let Some(i) = self.func_list[func_id].local_names.get_index_of(name) {
91 OpCode::StoreLocal(i)
92 } else if let Some(i) = self.func_list[func_id]
93 .global_names
94 .get_index_of(&GlobalNameInfo::from(name.to_owned()))
95 {
96 OpCode::StoreGlobal(i)
97 } else if let Some(i) = self.func_list[func_id]
98 .upvalue_names
99 .get_index_of(&UpvalueNameInfo::from(name.to_owned()))
100 {
101 OpCode::StoreUpvalue(i)
102 } else {
103 return Err(SyntaxError::IllegalAst);
104 };
105 self.func_list[func_id].code.push(t);
106 Ok(())
107 }
108
109 fn gen_code(&mut self, func_id: usize) -> Result<Code, SyntaxError> {
110 if let Some(variadic) = self.func_list[func_id].variadic.clone() {
111 self.store(func_id, &variadic)?;
112 }
113 for param in self.func_list[func_id].params.clone().into_iter().rev() {
114 self.store(func_id, ¶m)?;
115 }
116 for stmt in self.func_list[func_id].body.clone().body {
117 self.gen_stmt(func_id, &stmt)?;
118 }
119 if self.func_list[func_id].kind == FunctionKind::Do {
120 self.func_list[func_id].code.push(OpCode::Return);
121 } else if *self.func_list[func_id].code.last().unwrap_or(&OpCode::Pop) != OpCode::Return {
122 let t = self.add_const(func_id, ConstValue::Null);
123 self.func_list[func_id].code.push(OpCode::LoadConst(t));
124 self.func_list[func_id].code.push(OpCode::Return);
125 }
126
127 let mut temp: Vec<usize> = vec![0; self.func_list[func_id].jump_target_count];
128 let mut i = 0;
129 while i < self.func_list[func_id].code.len() {
130 match self.func_list[func_id].code[i] {
131 OpCode::JumpTarget(JumpTarget(index)) => {
132 temp[index] = i;
133 self.func_list[func_id].code.remove(i);
134 }
135 _ => i += 1,
136 }
137 }
138 let mut i = 0;
139 while i < self.func_list[func_id].code.len() {
140 match &self.func_list[func_id].code[i] {
141 OpCode::Jump(JumpTarget(v)) => {
142 self.func_list[func_id].code[i] = OpCode::Jump(JumpTarget(temp[*v]))
143 }
144 OpCode::JumpIfNull(JumpTarget(v)) => {
145 self.func_list[func_id].code[i] = OpCode::JumpIfNull(JumpTarget(temp[*v]))
146 }
147 OpCode::JumpPopIfFalse(JumpTarget(v)) => {
148 self.func_list[func_id].code[i] = OpCode::JumpPopIfFalse(JumpTarget(temp[*v]))
149 }
150 OpCode::JumpIfTrueOrPop(JumpTarget(v)) => {
151 self.func_list[func_id].code[i] = OpCode::JumpIfTrueOrPop(JumpTarget(temp[*v]))
152 }
153 OpCode::JumpIfFalseOrPop(JumpTarget(v)) => {
154 self.func_list[func_id].code[i] = OpCode::JumpIfFalseOrPop(JumpTarget(temp[*v]))
155 }
156 _ => (),
157 }
158 i += 1;
159 }
160
161 let stack_size = get_stack_size(
162 &self.func_list[func_id].code,
163 0,
164 self.func_list[func_id].params.len()
165 + if self.func_list[func_id].variadic.is_some() {
166 1
167 } else {
168 0
169 },
170 );
171 Ok(Code {
172 params: self.func_list[func_id].params.clone(),
173 variadic: self.func_list[func_id].variadic.clone(),
174 kind: self.func_list[func_id].kind,
175 code: self.func_list[func_id].code.clone(),
176 consts: self.func_list[func_id].consts.clone(),
177 local_names: self.func_list[func_id]
178 .local_names
179 .clone()
180 .into_iter()
181 .collect(),
182 global_names: self.func_list[func_id]
183 .global_names
184 .clone()
185 .into_iter()
186 .map(|x| x.name)
187 .collect(),
188 upvalue_names: self.func_list[func_id]
189 .upvalue_names
190 .clone()
191 .into_iter()
192 .map(|x| x.into())
193 .collect(),
194 def_upvalue_count: self.func_list[func_id].def_upvalue_count,
195 stack_size,
196 })
197 }
198
199 fn gen_expr(&mut self, func_id: usize, ast_node: &Expr) -> Result<(), SyntaxError> {
200 match &ast_node.kind {
201 ExprKind::Lit(lit) => {
202 let t = self.add_const(
203 func_id,
204 match &lit.value {
205 LitKind::Null => ConstValue::Null,
206 LitKind::Bool(v) => ConstValue::Bool(*v),
207 LitKind::Int(v) => ConstValue::Int(*v),
208 LitKind::Float(v) => ConstValue::Float(*v),
209 LitKind::Str(v) => ConstValue::Str(v.clone()),
210 },
211 );
212 self.func_list[func_id].code.push(OpCode::LoadConst(t));
213 }
214 ExprKind::Ident(ident) => self.load(func_id, &ident.name)?,
215 ExprKind::Function { .. } => return Err(SyntaxError::IllegalAst),
216 ExprKind::FunctionId(i) => {
217 let code = self.gen_code(*i)?;
218 let is_do = code.kind == FunctionKind::Do;
219 let t = self.add_const(func_id, ConstValue::Func(code));
220 self.func_list[func_id].code.push(OpCode::LoadConst(t));
221 if is_do {
222 self.func_list[func_id].code.push(OpCode::Call(0));
223 }
224 }
225 ExprKind::Table { properties } => {
226 let temp = properties.len();
227 for TableProperty { key, value, .. } in properties {
228 self.gen_expr(func_id, key)?;
229 self.gen_expr(func_id, value)?;
230 }
231 self.func_list[func_id].code.push(OpCode::BuildTable(temp));
232 }
233 ExprKind::List { items } => {
234 let temp = items.len();
235 for item in items {
236 self.gen_expr(func_id, item)?;
237 }
238 self.func_list[func_id].code.push(OpCode::BuildList(temp));
239 }
240 ExprKind::Unary { operator, argument } => {
241 self.gen_expr(func_id, argument)?;
242 self.func_list[func_id].code.push(match operator {
243 UnOp::Not => OpCode::Not,
244 UnOp::Neg => OpCode::Neg,
245 });
246 }
247 ExprKind::Binary {
248 operator,
249 left,
250 right,
251 } => match operator {
252 BinOp::And => {
253 let label = self.get_jump_target(func_id);
254 self.gen_expr(func_id, left)?;
255 self.func_list[func_id]
256 .code
257 .push(OpCode::JumpIfFalseOrPop(label));
258 self.gen_expr(func_id, right)?;
259 self.func_list[func_id].code.push(OpCode::JumpTarget(label));
260 }
261 BinOp::Or => {
262 let label = self.get_jump_target(func_id);
263 self.gen_expr(func_id, left)?;
264 self.func_list[func_id]
265 .code
266 .push(OpCode::JumpIfTrueOrPop(label));
267 self.gen_expr(func_id, right)?;
268 self.func_list[func_id].code.push(OpCode::JumpTarget(label));
269 }
270 operator => {
271 self.gen_expr(func_id, left)?;
272 self.gen_expr(func_id, right)?;
273 self.func_list[func_id]
274 .code
275 .push(OpCode::try_from(*operator)?);
276 }
277 },
278 ExprKind::Member {
279 table,
280 property,
281 kind,
282 safe,
283 } => {
284 self.gen_expr(func_id, table)?;
285 let safe_label = self.get_jump_target(func_id);
286 if *safe {
287 self.func_list[func_id]
288 .code
289 .push(OpCode::JumpIfNull(safe_label));
290 }
291 match kind {
292 MemberKind::Bracket => {
293 self.gen_expr(func_id, property)?;
294 self.func_list[func_id].code.push(OpCode::GetItem);
295 }
296 MemberKind::Dot | MemberKind::DoubleColon => {
297 match &property.kind {
298 ExprKind::Ident(ident) => {
299 let t =
300 self.add_const(func_id, ConstValue::Str(ident.name.clone()));
301 self.func_list[func_id].code.push(OpCode::LoadConst(t));
302 }
303 _ => return Err(SyntaxError::IllegalAst),
304 }
305 self.func_list[func_id].code.push(OpCode::GetAttr);
306 }
307 }
308 self.func_list[func_id]
309 .code
310 .push(OpCode::JumpTarget(safe_label));
311 }
312 ExprKind::MetaMember { table, safe } => {
313 self.gen_expr(func_id, table)?;
314 let safe_label = self.get_jump_target(func_id);
315 if *safe {
316 self.func_list[func_id]
317 .code
318 .push(OpCode::JumpIfNull(safe_label));
319 }
320 self.func_list[func_id].code.push(OpCode::GetMeta);
321 self.func_list[func_id]
322 .code
323 .push(OpCode::JumpTarget(safe_label));
324 }
325 ExprKind::Call {
326 callee,
327 arguments,
328 propagating_error,
329 } => {
330 let mut temp: usize = arguments.len();
331 let safe_label = self.get_jump_target(func_id);
332 match callee.kind.clone() {
333 ExprKind::Member {
334 table,
335 property,
336 kind,
337 safe,
338 } => {
339 self.gen_expr(func_id, &table)?;
340 if safe {
341 self.func_list[func_id]
342 .code
343 .push(OpCode::JumpIfNull(safe_label));
344 }
345 match kind {
346 MemberKind::Bracket => {
347 self.gen_expr(func_id, &property)?;
348 self.func_list[func_id].code.push(OpCode::GetItem);
349 }
350 MemberKind::Dot => {
351 self.func_list[func_id].code.push(OpCode::Copy(1));
352 match property.kind {
353 ExprKind::Ident(ident) => {
354 let t =
355 self.add_const(func_id, ConstValue::Str(ident.name));
356 self.func_list[func_id].code.push(OpCode::LoadConst(t));
357 }
358 _ => return Err(SyntaxError::IllegalAst),
359 }
360 self.func_list[func_id].code.push(OpCode::GetAttr);
361 self.func_list[func_id].code.push(OpCode::Swap(2));
362 temp += 1;
363 }
364 MemberKind::DoubleColon => {
365 match property.kind {
366 ExprKind::Ident(ident) => {
367 let t =
368 self.add_const(func_id, ConstValue::Str(ident.name));
369 self.func_list[func_id].code.push(OpCode::LoadConst(t));
370 }
371 _ => return Err(SyntaxError::IllegalAst),
372 }
373 self.func_list[func_id].code.push(OpCode::GetAttr);
374 }
375 }
376 }
377 _ => {
378 self.gen_expr(func_id, callee)?;
379 }
380 }
381 for arg in arguments {
382 self.gen_expr(func_id, arg)?;
383 }
384 self.func_list[func_id].code.push(if *propagating_error {
385 OpCode::TryCall(temp)
386 } else {
387 OpCode::Call(temp)
388 });
389 self.func_list[func_id]
390 .code
391 .push(OpCode::JumpTarget(safe_label));
392 }
393 }
394 Ok(())
395 }
396
397 fn gen_stmt(&mut self, func_id: usize, ast_node: &Stmt) -> Result<(), SyntaxError> {
398 macro_rules! gen_block {
399 ($block:expr) => {
400 for stmt in &$block.body {
401 self.gen_stmt(func_id, stmt)?;
402 }
403 };
404 }
405 macro_rules! gen_expr_member_without_get {
406 ($table:expr, $property:expr, $kind:expr, $safe:expr) => {{
407 if *$safe {
408 return Err(SyntaxError::IllegalAst);
409 }
410 self.gen_expr(func_id, &$table)?;
411 match $kind {
412 MemberKind::Bracket => self.gen_expr(func_id, &$property)?,
413 MemberKind::Dot | MemberKind::DoubleColon => match &$property.kind {
414 ExprKind::Ident(ident) => {
415 let t = self.add_const(func_id, ConstValue::Str(ident.name.clone()));
416 self.func_list[func_id].code.push(OpCode::LoadConst(t));
417 }
418 _ => return Err(SyntaxError::IllegalAst),
419 },
420 }
421 }};
422 }
423 macro_rules! assign_left {
424 ($left:expr) => {
425 match &$left.kind {
426 ExprKind::Ident(ident) => self.store(func_id, &ident.name)?,
427 ExprKind::Member {
428 table,
429 property,
430 kind,
431 safe,
432 } => {
433 gen_expr_member_without_get!(table, property, kind, safe);
434 self.func_list[func_id].code.push(match kind {
435 MemberKind::Bracket => OpCode::SetItem,
436 MemberKind::Dot | MemberKind::DoubleColon => OpCode::SetAttr,
437 });
438 }
439 ExprKind::MetaMember { table, safe } => {
440 if *safe {
441 return Err(SyntaxError::IllegalAst);
442 }
443 self.gen_expr(func_id, table)?;
444 self.func_list[func_id].code.push(OpCode::SetMeta);
445 }
446 _ => return Err(SyntaxError::IllegalAst),
447 }
448 };
449 }
450 match &ast_node.kind {
451 StmtKind::If {
452 test,
453 consequent,
454 alternate,
455 } => {
456 if let Some(alternate) = alternate {
468 let false_label = self.get_jump_target(func_id);
469 let end_label = self.get_jump_target(func_id);
470 self.gen_expr(func_id, test)?;
471 self.func_list[func_id]
472 .code
473 .push(OpCode::JumpPopIfFalse(false_label));
474 gen_block!(consequent);
475 self.func_list[func_id].code.push(OpCode::Jump(end_label));
476 self.func_list[func_id]
477 .code
478 .push(OpCode::JumpTarget(false_label));
479 self.gen_stmt(func_id, alternate)?;
480 self.func_list[func_id]
481 .code
482 .push(OpCode::JumpTarget(end_label));
483 } else {
484 let end_label = self.get_jump_target(func_id);
485 self.gen_expr(func_id, test)?;
486 self.func_list[func_id]
487 .code
488 .push(OpCode::JumpPopIfFalse(end_label));
489 gen_block!(consequent);
490 self.func_list[func_id]
491 .code
492 .push(OpCode::JumpTarget(end_label));
493 }
494 }
495 StmtKind::Loop { body } => {
496 let continue_label = self.get_jump_target(func_id);
497 let break_label = self.get_jump_target(func_id);
498 self.func_list[func_id].continue_stack.push(continue_label);
499 self.func_list[func_id].break_stack.push(break_label);
500
501 self.func_list[func_id]
502 .code
503 .push(OpCode::JumpTarget(continue_label));
504 gen_block!(body);
505 self.func_list[func_id]
506 .code
507 .push(OpCode::Jump(continue_label));
508 self.func_list[func_id]
509 .code
510 .push(OpCode::JumpTarget(break_label));
511
512 self.func_list[func_id].continue_stack.pop();
513 self.func_list[func_id].break_stack.pop();
514 }
515 StmtKind::While { test, body } => {
516 let continue_label = self.get_jump_target(func_id);
517 let break_label = self.get_jump_target(func_id);
518 self.func_list[func_id].continue_stack.push(continue_label);
519 self.func_list[func_id].break_stack.push(break_label);
520
521 self.func_list[func_id]
522 .code
523 .push(OpCode::JumpTarget(continue_label));
524 self.gen_expr(func_id, test)?;
525 self.func_list[func_id]
526 .code
527 .push(OpCode::JumpPopIfFalse(break_label));
528 gen_block!(body);
529 self.func_list[func_id]
530 .code
531 .push(OpCode::Jump(continue_label));
532 self.func_list[func_id]
533 .code
534 .push(OpCode::JumpTarget(break_label));
535
536 self.func_list[func_id].continue_stack.pop();
537 self.func_list[func_id].break_stack.pop();
538 }
539 StmtKind::For { left, right, body } => {
540 let continue_label = self.get_jump_target(func_id);
541 let break_label = self.get_jump_target(func_id);
542 self.func_list[func_id].continue_stack.push(continue_label);
543 self.func_list[func_id].break_stack.push(break_label);
544
545 self.gen_expr(func_id, right)?;
546 self.func_list[func_id].code.push(OpCode::Iter);
547 self.func_list[func_id]
548 .code
549 .push(OpCode::JumpTarget(continue_label));
550 self.func_list[func_id].code.push(OpCode::Copy(1));
551 self.func_list[func_id].code.push(OpCode::Call(0));
552 self.func_list[func_id]
553 .code
554 .push(OpCode::JumpIfNull(break_label));
555 if left.len() == 1 {
556 self.store(func_id, &left[0].name)?;
557 } else {
558 for (i, l) in left.iter().enumerate() {
559 self.func_list[func_id].code.push(OpCode::Copy(1));
560 let t = self.add_const(func_id, ConstValue::Int(i.try_into().unwrap()));
561 self.func_list[func_id].code.push(OpCode::LoadConst(t));
562 self.func_list[func_id].code.push(OpCode::GetItem);
563 self.store(func_id, &l.name)?;
564 }
565 self.func_list[func_id].code.push(OpCode::Pop);
566 }
567 gen_block!(body);
568 self.func_list[func_id]
569 .code
570 .push(OpCode::Jump(continue_label));
571 self.func_list[func_id]
572 .code
573 .push(OpCode::JumpTarget(break_label));
574 self.func_list[func_id].code.push(OpCode::Pop);
575 self.func_list[func_id].code.push(OpCode::Pop);
576
577 self.func_list[func_id].continue_stack.pop();
578 self.func_list[func_id].break_stack.pop();
579 }
580 StmtKind::Break => {
581 let t = OpCode::Jump(match self.func_list[func_id].break_stack.last() {
582 Some(v) => *v,
583 None => return Err(SyntaxError::BreakOutsideLoop),
584 });
585 self.func_list[func_id].code.push(t);
586 }
587 StmtKind::Continue => {
588 let t = OpCode::Jump(match self.func_list[func_id].continue_stack.last() {
589 Some(v) => *v,
590 None => return Err(SyntaxError::ContinueOutsideLoop),
591 });
592 self.func_list[func_id].code.push(t);
593 }
594 StmtKind::Return { argument } => {
595 if self.func_list[func_id].kind == FunctionKind::Do {
596 return Err(SyntaxError::ReturnOutsideFunction);
597 }
598 if let ExprKind::Call {
599 propagating_error, ..
600 } = argument.kind
601 {
602 self.gen_expr(func_id, argument)?;
603 if propagating_error {
604 self.func_list[func_id].code.push(OpCode::Return);
605 } else if let OpCode::Call(i) =
606 self.func_list[func_id].code[self.func_list[func_id].code.len() - 2]
607 {
608 let t = self.func_list[func_id].code.len();
609 self.func_list[func_id].code[t - 2] = OpCode::ReturnCall(i);
610 }
611 } else {
612 self.gen_expr(func_id, argument)?;
613 self.func_list[func_id].code.push(OpCode::Return);
614 }
615 }
616 StmtKind::Throw { argument } => {
617 if self.func_list[func_id].kind == FunctionKind::Do {
618 return Err(SyntaxError::ThrowOutsideFunction);
619 }
620 self.gen_expr(func_id, argument)?;
621 self.func_list[func_id].code.push(OpCode::Throw);
622 }
623 StmtKind::Global { arguments } => {
624 if self.func_list[func_id].kind == FunctionKind::Do {
625 return Err(SyntaxError::GlobalOutsideFunction);
626 }
627 for arg in arguments {
628 self.func_list[func_id].global_names.insert(GlobalNameInfo {
629 name: arg.name.clone(),
630 is_writable: true,
631 });
632 }
633 }
634 StmtKind::Import { path, kind } => {
635 let path_str = path.iter().map(|x| x.name.as_str()).join("::");
636 let t = self.add_const(func_id, ConstValue::Str(path_str));
637 self.func_list[func_id].code.push(OpCode::Import(t));
638 match kind {
639 ImportKind::Simple(alias) => self.store(func_id, &alias.name)?,
640 ImportKind::Nested(items) => {
641 for (name, alias) in items {
642 let t = self.add_const(func_id, ConstValue::Str(name.name.clone()));
643 self.func_list[func_id].code.push(OpCode::ImportFrom(t));
644 self.store(func_id, &alias.name)?;
645 }
646 self.func_list[func_id].code.push(OpCode::Pop);
647 }
648 ImportKind::Glob => {
649 self.func_list[func_id].code.push(OpCode::ImportGlob);
650 }
651 }
652 }
653 StmtKind::Assign { left, right } => {
654 self.gen_expr(func_id, right)?;
655 assign_left!(left);
656 }
657 StmtKind::AssignOp {
658 operator,
659 left,
660 right,
661 } => match &left.kind {
662 ExprKind::Ident(ident) => {
663 self.gen_expr(func_id, left)?;
664 self.gen_expr(func_id, right)?;
665 self.func_list[func_id]
666 .code
667 .push(OpCode::try_from(*operator)?);
668 self.store(func_id, &ident.name)?;
669 }
670 ExprKind::Member {
671 table,
672 property,
673 kind,
674 safe,
675 } => {
676 gen_expr_member_without_get!(table, property, kind, safe);
677 self.func_list[func_id].code.push(OpCode::Copy(2));
678 self.func_list[func_id].code.push(OpCode::Copy(2));
679 self.func_list[func_id].code.push(match kind {
680 MemberKind::Bracket => OpCode::GetItem,
681 MemberKind::Dot | MemberKind::DoubleColon => OpCode::GetAttr,
682 });
683 self.gen_expr(func_id, right)?;
684 self.func_list[func_id]
685 .code
686 .push(OpCode::try_from(*operator)?);
687 self.func_list[func_id].code.push(OpCode::Swap(3));
688 self.func_list[func_id].code.push(OpCode::Swap(2));
689 self.func_list[func_id].code.push(match kind {
690 MemberKind::Bracket => OpCode::SetItem,
691 MemberKind::Dot | MemberKind::DoubleColon => OpCode::SetAttr,
692 });
693 }
694 ExprKind::MetaMember { table, safe } => {
695 if *safe {
696 return Err(SyntaxError::IllegalAst);
697 }
698 self.gen_expr(func_id, table)?;
699 self.func_list[func_id].code.push(OpCode::Copy(1));
700 self.func_list[func_id].code.push(OpCode::GetMeta);
701 self.func_list[func_id].code.push(OpCode::SetMeta);
702 }
703 _ => return Err(SyntaxError::IllegalAst),
704 },
705 StmtKind::AssignUnpack { left, right } => {
706 self.gen_expr(func_id, right)?;
707 for (i, l) in left.iter().enumerate() {
708 let t = self.add_const(func_id, ConstValue::Int(i.try_into().unwrap()));
709 self.func_list[func_id].code.push(OpCode::LoadConst(t));
710 self.func_list[func_id].code.push(OpCode::GetItem);
711 assign_left!(l);
712 }
713 }
714 StmtKind::AssignMulti { left, right } => {
715 if left.len() != right.len() {
716 return Err(SyntaxError::IllegalAst);
717 }
718 for right in right {
719 self.gen_expr(func_id, right)?;
720 }
721 for left in left.iter().rev() {
722 assign_left!(left);
723 }
724 }
725 StmtKind::Block(block) => gen_block!(block),
726 StmtKind::Expr(expr) => {
727 self.gen_expr(func_id, expr)?;
728 self.func_list[func_id].code.push(OpCode::Pop);
729 }
730 }
731 Ok(())
732 }
733}
734
735fn get_stack_size(code: &Vec<OpCode>, mut offset: usize, init_size: usize) -> usize {
737 let mut stack_size = init_size;
738 let mut t = init_size;
739 while offset < code.len() {
740 match code[offset] {
741 OpCode::Pop => t += 1,
742 OpCode::Copy(_) => t += 1,
743 OpCode::Swap(_) => (),
744 OpCode::LoadLocal(_)
745 | OpCode::LoadGlobal(_)
746 | OpCode::LoadUpvalue(_)
747 | OpCode::LoadConst(_) => t += 1,
748 OpCode::StoreLocal(_) | OpCode::StoreGlobal(_) | OpCode::StoreUpvalue(_) => t -= 1,
749 OpCode::Import(_) => t += 1,
750 OpCode::ImportFrom(_) => t += 1,
751 OpCode::ImportGlob => (),
752 OpCode::BuildTable(i) => t = t - i * 2 + 1,
753 OpCode::BuildList(i) => t = t - i + 1,
754 OpCode::GetAttr | OpCode::GetItem => t -= 1,
755 OpCode::GetMeta => (),
756 OpCode::SetAttr | OpCode::SetItem => t -= 2,
757 OpCode::SetMeta => t -= 1,
758 OpCode::Neg | OpCode::Not => (),
759 OpCode::Add
760 | OpCode::Sub
761 | OpCode::Mul
762 | OpCode::Div
763 | OpCode::Mod
764 | OpCode::Eq
765 | OpCode::Ne
766 | OpCode::Gt
767 | OpCode::Ge
768 | OpCode::Lt
769 | OpCode::Le
770 | OpCode::Is => t -= 1,
771 OpCode::Iter => (),
772 OpCode::Jump(JumpTarget(_)) => (),
773 OpCode::JumpIfNull(JumpTarget(i)) => {
774 stack_size = stack_size.max(get_stack_size(code, i, t));
775 }
776 OpCode::JumpPopIfFalse(JumpTarget(i)) => {
777 t -= 1;
778 stack_size = stack_size.max(get_stack_size(code, i, t));
779 }
780 OpCode::JumpIfTrueOrPop(JumpTarget(i)) | OpCode::JumpIfFalseOrPop(JumpTarget(i)) => {
781 stack_size = stack_size.max(get_stack_size(code, i, t));
782 t -= 1;
783 }
784 OpCode::Call(i) => t = t - i + 1,
785 OpCode::TryCall(i) => t = t - i + 1,
786 OpCode::Return | OpCode::Throw => break,
787 OpCode::ReturnCall(i) => t = t - i + 1,
788 OpCode::JumpTarget(_) => panic!(),
789 }
790 stack_size = stack_size.max(t);
791 offset += 1;
792 }
793 stack_size
794}
795
796#[derive(Error, Debug, Clone, PartialEq)]
798pub enum SyntaxError {
799 #[error("illegal ast")]
800 IllegalAst,
801 #[error("break outside loop")]
802 BreakOutsideLoop,
803 #[error("continue outside loop")]
804 ContinueOutsideLoop,
805 #[error("global outside function")]
806 GlobalOutsideFunction,
807 #[error("return outside function")]
808 ReturnOutsideFunction,
809 #[error("throw outside function")]
810 ThrowOutsideFunction,
811 #[error(transparent)]
812 ParserError(#[from] ParserError),
813}