現在のアプローチでは、対応するコードを生成する前に子の実際のタイプをチェックするために複数の条件ステートメントを使用する必要があるため、ビジターパターンを使用するようにコンパイラのコードジェネレータを変更したいと思います。ただし、訪問後に子の属性を取得するのに問題があります。たとえば、バイナリ式では次のように使用します。
LHSCode := GenerateExpressionCode(LHSNode);
RHSCode := GenerateExpressionCode(RHSNode);
CreateBinaryExpression(Self,LHS,RHS);
ビジターパターンでは、visitメソッドは通常無効であるため、LHSおよびRHSから式コードを取得できません。式コードの生成は再帰的であり、変数に保持されている以前の値を消去する可能性があるため、共有グローバル変数を保持することはオプションではありません。
これは(今のところ)最も複雑な部分であるため、バイナリ式を示します。
function TLLVMCodeGenerator.GenerateExpressionCode(
Expr: TASTExpression): TLLVMValue;
var
BinExpr: TASTBinaryExpression;
UnExpr: TASTUnaryExpression;
LHSCode, RHSCode, ExprCode: TLLVMValue;
VarExpr: TASTVariableExpression;
begin
if Expr is TASTBinaryExpression then begin
BinExpr := Expr as TASTBinaryExpression;
LHSCode := GenerateExpressionCode(BinExpr.LHS);
RHSCode := GenerateExpressionCode(BinExpr.RHS);
case BinExpr.Op of
'<': Result := FBuilder.CreateICmp(ccSLT, LHSCode, RHSCode);
'<=': Result := FBuilder.CreateICmp(ccSLE, LHSCode, RHSCode);
'>': Result := FBuilder.CreateICmp(ccSGT, LHSCode, RHSCode);
'>=': Result := FBuilder.CreateICmp(ccSGE, LHSCode, RHSCode);
'==': Result := FBuilder.CreateICmp(ccEQ, LHSCode, RHSCode);
'<>': Result := FBuilder.CreateICmp(ccNE, LHSCode, RHSCode);
'/\': Result := FBuilder.CreateAnd(LHSCode, RHSCode);
'\/': Result := FBuilder.CreateOr(LHSCode, RHSCode);
'+': Result := FBuilder.CreateAdd(LHSCode, RHSCode);
'-': Result := FBuilder.CreateSub(LHSCode, RHSCode);
'*': Result := FBuilder.CreateMul(LHSCode, RHSCode);
'/': Result := FBuilder.CreateSDiv(LHSCode, RHSCode);
end;
end else if Expr is TASTPrimaryExpression then
if Expr is TASTBooleanConstant then
with Expr as TASTBooleanConstant do
Result := FBuilder.CreateConstant(Ord(Value), ltI1)
else if Expr is TASTIntegerConstant then
with Expr as TASTIntegerConstant do
Result := FBuilder.CreateConstant(Value, ltI32)
else if Expr is TASTUnaryExpression then begin
UnExpr := Expr as TASTUnaryExpression;
ExprCode := GenerateExpressionCode(UnExpr.Expr);
case UnExpr.Op of
'~': Result := FBuilder.CreateXor(
FBuilder.CreateConstant(1, ltI1), ExprCode);
'-': Result := FBuilder.CreateSub(
FBuilder.CreateConstant(0, ltI32), ExprCode);
end;
end else if Expr is TASTVariableExpression then begin
VarExpr := Expr as TASTVariableExpression;
with VarExpr.VarDecl do
Result := FBuilder.CreateVar(Ident, BaseTypeLLVMTypeMap[BaseType]);
end;
end;
あなたがそれを理解することを願っています:)