- added processing of compound statements to the compiler. This means that anonymous functions without control statements are generating code now.
- added local variable declarations to the code generator. This is not tested yet, that will come with the next commit.
This commit is contained in:
parent
8a6230d64a
commit
2d85efce2a
4 changed files with 232 additions and 5 deletions
|
|
@ -5023,14 +5023,18 @@ ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
Outer = ctx.Block;
|
||||
ctx.Block = this;
|
||||
for (unsigned i = 0; i < Expressions.Size(); ++i)
|
||||
{
|
||||
if (NULL == (Expressions[i] = Expressions[i]->Resolve(ctx)))
|
||||
{
|
||||
ctx.Block = Outer;
|
||||
delete this;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
ctx.Block = Outer;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -5048,6 +5052,11 @@ ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build)
|
|||
// Throw away any result. We don't care about it.
|
||||
v.Free(build);
|
||||
}
|
||||
// Release all local variables in this block.
|
||||
for (auto l : LocalVars)
|
||||
{
|
||||
l->Release(build);
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
|
|
@ -5066,6 +5075,52 @@ VMFunction *FxCompoundStatement::GetDirectFunction()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxCompoundStatement :: FindLocalVariable
|
||||
//
|
||||
// Looks for a variable name in any of the containing compound statements
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name)
|
||||
{
|
||||
auto block = this;
|
||||
while (block != nullptr)
|
||||
{
|
||||
for (auto l : block->LocalVars)
|
||||
{
|
||||
if (l->Name == name)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
}
|
||||
block = block->Outer;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxCompoundStatement :: CheckLocalVariable
|
||||
//
|
||||
// Checks if the current block already contains a local variable
|
||||
// of the given name.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FxCompoundStatement::CheckLocalVariable(FName name)
|
||||
{
|
||||
for (auto l : LocalVars)
|
||||
{
|
||||
if (l->Name == name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxIfStatement
|
||||
|
|
@ -6142,3 +6197,87 @@ ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build)
|
|||
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// declares a single local variable (no arrays)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p)
|
||||
:FxExpression(p)
|
||||
{
|
||||
ValueType = type;
|
||||
Name = name;
|
||||
Init = initval == nullptr? nullptr : new FxTypeCast(initval, type, false);
|
||||
}
|
||||
|
||||
FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE_OPT(Init, ctx);
|
||||
if (ctx.Block == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Variable declaration outside compound statement");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
ctx.Block->LocalVars.Push(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
if (Init == nullptr)
|
||||
{
|
||||
RegNum = build->Registers[ValueType->GetRegType()].Get(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpEmit emitval = Init->Emit(build);
|
||||
|
||||
int regtype = emitval.RegType;
|
||||
if (regtype < REGT_INT || regtype > REGT_TYPE)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Attempted to assign a non-value");
|
||||
return ExpEmit();
|
||||
}
|
||||
if (emitval.Konst)
|
||||
{
|
||||
auto constval = static_cast<FxConstant *>(Init);
|
||||
RegNum = build->Registers[regtype].Get(1);
|
||||
switch (regtype)
|
||||
{
|
||||
default:
|
||||
case REGT_INT:
|
||||
build->Emit(OP_LK, build->GetConstantInt(constval->GetValue().GetInt()), RegNum);
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
build->Emit(OP_LKF, build->GetConstantFloat(constval->GetValue().GetFloat()), RegNum);
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
build->Emit(OP_LKP, build->GetConstantAddress(constval->GetValue().GetPointer(), ATAG_GENERIC), RegNum);
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
build->Emit(OP_LKS, build->GetConstantString(constval->GetValue().GetString()), RegNum);
|
||||
}
|
||||
emitval.Free(build);
|
||||
}
|
||||
else
|
||||
{
|
||||
// take over the register that got allocated while emitting the Init expression.
|
||||
RegNum = emitval.RegNum;
|
||||
}
|
||||
}
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
|
||||
{
|
||||
// Release the register after the containing block gets closed
|
||||
assert(RegNum != -1);
|
||||
build->Registers[ValueType->GetRegType()].Return(RegNum, 1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue