Phase 4: Steuerelemente implementieren
This commit is contained in:
@@ -20,6 +20,10 @@ pub fn compile(hir: &HirModule) -> CompiledModule {
|
||||
string_ids: HashMap::new(),
|
||||
jump_tables: Vec::new(),
|
||||
modul_label_pc: Vec::new(),
|
||||
initialize_main: hir
|
||||
.objects
|
||||
.iter()
|
||||
.any(|object| object.class == tb_frontend::forms::ObjectClass::Form),
|
||||
};
|
||||
let mut procs = Vec::new();
|
||||
for proc in &hir.procs {
|
||||
@@ -29,7 +33,7 @@ pub fn compile(hir: &HirModule) -> CompiledModule {
|
||||
name: hir.name.clone(),
|
||||
option_base: hir.option_base,
|
||||
strings: cg.strings,
|
||||
globals_init: hir.globals.iter().map(|g| slot_init(g)).collect(),
|
||||
globals_init: hir.globals.iter().map(slot_init).collect(),
|
||||
global_names: hir.globals.iter().map(|g| g.name.clone()).collect(),
|
||||
udts: hir
|
||||
.udts
|
||||
@@ -85,6 +89,9 @@ struct Codegen {
|
||||
/// `ON ERROR GOTO` aus einer Prozedur zeigt dorthin; da Prozedur 0
|
||||
/// zuerst übersetzt wird, stehen die Positionen rechtzeitig fest.
|
||||
modul_label_pc: Vec<Option<u32>>,
|
||||
/// Formulare müssen erst nach den globalen DIM-Anweisungen Ereignisse
|
||||
/// zustellen; reine Textprogramme behalten ihre bisherigen Grenzen.
|
||||
initialize_main: bool,
|
||||
}
|
||||
|
||||
struct ProcCtx {
|
||||
@@ -160,7 +167,30 @@ impl Codegen {
|
||||
fixups: Vec::new(),
|
||||
table_fixups: Vec::new(),
|
||||
};
|
||||
if proc.kind == hir::HProcKind::Main {
|
||||
let declarations = proc
|
||||
.body
|
||||
.iter()
|
||||
.filter(|stmt| matches!(stmt.kind, HStmtKind::Dim { redim: false, .. }))
|
||||
.collect::<Vec<_>>();
|
||||
for stmt in declarations {
|
||||
self.stmt_inner(&mut ctx, proc, stmt, false);
|
||||
}
|
||||
if self.initialize_main
|
||||
|| proc
|
||||
.body
|
||||
.iter()
|
||||
.any(|stmt| matches!(stmt.kind, HStmtKind::Dim { redim: false, .. }))
|
||||
{
|
||||
ctx.emit(Instr::Stmt(0));
|
||||
}
|
||||
}
|
||||
for stmt in &proc.body {
|
||||
if proc.kind == hir::HProcKind::Main
|
||||
&& matches!(stmt.kind, HStmtKind::Dim { redim: false, .. })
|
||||
{
|
||||
continue;
|
||||
}
|
||||
self.stmt(&mut ctx, proc, stmt);
|
||||
}
|
||||
// Rumpfende
|
||||
@@ -234,12 +264,17 @@ impl Codegen {
|
||||
// ---- Anweisungen -------------------------------------------------------
|
||||
|
||||
fn stmt(&mut self, ctx: &mut ProcCtx, proc: &hir::HProc, stmt: &HStmt) {
|
||||
self.stmt_inner(ctx, proc, stmt, true);
|
||||
}
|
||||
|
||||
fn stmt_inner(&mut self, ctx: &mut ProcCtx, proc: &hir::HProc, stmt: &HStmt, boundary: bool) {
|
||||
match &stmt.kind {
|
||||
HStmtKind::Label(l) => {
|
||||
ctx.bind(*l);
|
||||
return;
|
||||
}
|
||||
_ => ctx.emit(Instr::Stmt(stmt.line)),
|
||||
_ if boundary => ctx.emit(Instr::Stmt(stmt.line)),
|
||||
_ => {}
|
||||
}
|
||||
match &stmt.kind {
|
||||
HStmtKind::Label(_) => unreachable!(),
|
||||
@@ -263,6 +298,23 @@ impl Codegen {
|
||||
index.is_some(),
|
||||
));
|
||||
}
|
||||
HStmtKind::SetObjectIndexedProperty {
|
||||
object,
|
||||
object_index,
|
||||
property,
|
||||
index,
|
||||
value,
|
||||
} => {
|
||||
if let Some(object_index) = object_index {
|
||||
self.expr(ctx, object_index);
|
||||
}
|
||||
self.expr(ctx, index);
|
||||
self.expr(ctx, value);
|
||||
ctx.emit(Instr::StoreObjectIndexedProperty(
|
||||
*object,
|
||||
*property | if object_index.is_some() { 0x8000 } else { 0 },
|
||||
));
|
||||
}
|
||||
HStmtKind::SetDynamicObjectProperty {
|
||||
object,
|
||||
property,
|
||||
@@ -275,13 +327,21 @@ impl Codegen {
|
||||
}
|
||||
HStmtKind::ObjectMethod {
|
||||
object,
|
||||
index,
|
||||
method,
|
||||
args,
|
||||
} => {
|
||||
if let Some(index) = index {
|
||||
self.expr(ctx, index);
|
||||
}
|
||||
for arg in args {
|
||||
self.expr(ctx, arg);
|
||||
}
|
||||
ctx.emit(Instr::ObjectMethod(*object, *method, args.len() as u8));
|
||||
ctx.emit(Instr::ObjectMethod(
|
||||
*object,
|
||||
*method,
|
||||
args.len() as u8 | if index.is_some() { 0x80 } else { 0 },
|
||||
));
|
||||
}
|
||||
HStmtKind::ObjectLoad {
|
||||
object,
|
||||
@@ -509,6 +569,18 @@ impl Codegen {
|
||||
None => ctx.emit(Instr::RetGosub),
|
||||
Some(l) => ctx.emit_jump(Instr::RetGosubTo(0), *l),
|
||||
},
|
||||
HStmtKind::Run { target, string } => {
|
||||
if let Some(target) = target {
|
||||
self.expr(ctx, target);
|
||||
}
|
||||
ctx.emit(Instr::Run(if target.is_none() {
|
||||
0
|
||||
} else if *string {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
}));
|
||||
}
|
||||
HStmtKind::ExitProc => self.emit_proc_exit(ctx, proc),
|
||||
HStmtKind::CallSub { proc: id, args } => {
|
||||
for a in args {
|
||||
@@ -533,6 +605,9 @@ impl Codegen {
|
||||
}
|
||||
let id = builtin_id(*b);
|
||||
ctx.emit(Instr::CallBuiltin(id, args.len() as u8));
|
||||
if matches!(b, Builtin::MsgBox) {
|
||||
ctx.emit(Instr::Pop);
|
||||
}
|
||||
if builtin_returns_value(*b) {
|
||||
ctx.emit(Instr::Pop);
|
||||
}
|
||||
@@ -725,6 +800,41 @@ impl Codegen {
|
||||
index.is_some(),
|
||||
));
|
||||
}
|
||||
HExpr::ObjectIndexedProperty {
|
||||
object,
|
||||
object_index,
|
||||
property,
|
||||
index,
|
||||
..
|
||||
} => {
|
||||
if let Some(object_index) = object_index {
|
||||
self.expr(ctx, object_index);
|
||||
}
|
||||
self.expr(ctx, index);
|
||||
ctx.emit(Instr::LoadObjectIndexedProperty(
|
||||
*object,
|
||||
*property | if object_index.is_some() { 0x8000 } else { 0 },
|
||||
));
|
||||
}
|
||||
HExpr::ObjectMethodCall {
|
||||
object,
|
||||
index,
|
||||
method,
|
||||
args,
|
||||
..
|
||||
} => {
|
||||
if let Some(index) = index {
|
||||
self.expr(ctx, index);
|
||||
}
|
||||
for arg in args {
|
||||
self.expr(ctx, arg);
|
||||
}
|
||||
ctx.emit(Instr::ObjectMethodFn(
|
||||
*object,
|
||||
*method,
|
||||
args.len() as u8 | if index.is_some() { 0x80 } else { 0 },
|
||||
));
|
||||
}
|
||||
HExpr::DynamicObjectProperty { object, property } => {
|
||||
self.expr(ctx, object);
|
||||
let property = self.pool(property);
|
||||
@@ -1173,6 +1283,9 @@ fn builtin_id(b: Builtin) -> u16 {
|
||||
Builtin::Width => ids::WIDTH,
|
||||
Builtin::ViewPrint => ids::VIEW_PRINT,
|
||||
Builtin::ScreenStmt => ids::SCREEN_STMT,
|
||||
Builtin::GraphicsLine => ids::GRAPHICS_LINE,
|
||||
Builtin::GraphicsPaint => ids::GRAPHICS_PAINT,
|
||||
Builtin::GraphicsView => ids::GRAPHICS_VIEW,
|
||||
Builtin::KeyAssign => ids::KEY_ASSIGN,
|
||||
Builtin::KeyList => ids::KEY_LIST,
|
||||
Builtin::KeyDisplay => ids::KEY_DISPLAY,
|
||||
@@ -1277,6 +1390,10 @@ fn builtin_id(b: Builtin) -> u16 {
|
||||
Builtin::IsamSavepoint => ids::ISAM_SAVEPOINT,
|
||||
Builtin::IsamSetmem => ids::ISAM_SETMEM,
|
||||
Builtin::IsamBof => ids::ISAM_BOF,
|
||||
Builtin::MsgBox => ids::MSGBOX,
|
||||
Builtin::InputBoxS => ids::INPUTBOX_S,
|
||||
Builtin::ClipboardAdd => ids::CLIPBOARD_ADD,
|
||||
Builtin::ClipboardGet => ids::CLIPBOARD_GET,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user