OpenClonk
C4AulCompiler::CodegenAstVisitor Class Reference
Inheritance diagram for C4AulCompiler::CodegenAstVisitor:
[legend]
Collaboration diagram for C4AulCompiler::CodegenAstVisitor:
[legend]

Public Member Functions

 CodegenAstVisitor (C4ScriptHost *host, C4ScriptHost *source_host)
 
 CodegenAstVisitor (C4AulScriptFunc *func)
 
 ~CodegenAstVisitor () override=default
 
void visit (const ::aul::ast::Noop *) override
 
void visit (const ::aul::ast::StringLit *n) override
 
void visit (const ::aul::ast::IntLit *n) override
 
void visit (const ::aul::ast::BoolLit *n) override
 
void visit (const ::aul::ast::ArrayLit *n) override
 
void visit (const ::aul::ast::ProplistLit *n) override
 
void visit (const ::aul::ast::NilLit *n) override
 
void visit (const ::aul::ast::ThisLit *n) override
 
void visit (const ::aul::ast::VarExpr *n) override
 
void visit (const ::aul::ast::UnOpExpr *n) override
 
void visit (const ::aul::ast::BinOpExpr *n) override
 
void visit (const ::aul::ast::AssignmentExpr *n) override
 
void visit (const ::aul::ast::SubscriptExpr *n) override
 
void visit (const ::aul::ast::SliceExpr *n) override
 
void visit (const ::aul::ast::CallExpr *n) override
 
void visit (const ::aul::ast::ParExpr *n) override
 
void visit (const ::aul::ast::Block *n) override
 
void visit (const ::aul::ast::Return *n) override
 
void visit (const ::aul::ast::ForLoop *n) override
 
void visit (const ::aul::ast::RangeLoop *n) override
 
void visit (const ::aul::ast::DoLoop *n) override
 
void visit (const ::aul::ast::WhileLoop *n) override
 
void visit (const ::aul::ast::Break *n) override
 
void visit (const ::aul::ast::Continue *n) override
 
void visit (const ::aul::ast::If *n) override
 
void visit (const ::aul::ast::VarDecl *n) override
 
void visit (const ::aul::ast::FunctionDecl *n) override
 
void visit (const ::aul::ast::FunctionExpr *n) override
 
void visit (const ::aul::ast::Script *n) override
 
template<class T >
void EmitFunctionCode (const T *n)
 
virtual void visit (const ::aul::ast::IncludePragma *)
 
virtual void visit (const ::aul::ast::AppendtoPragma *)
 
template<class T >
void visit (const T *)=delete
 

Detailed Description

Definition at line 150 of file C4AulCompiler.cpp.

Constructor & Destructor Documentation

◆ CodegenAstVisitor() [1/2]

C4AulCompiler::CodegenAstVisitor::CodegenAstVisitor ( C4ScriptHost host,
C4ScriptHost source_host 
)
inline

Definition at line 267 of file C4AulCompiler.cpp.

267 : target_host(host), host(source_host) {}

◆ CodegenAstVisitor() [2/2]

C4AulCompiler::CodegenAstVisitor::CodegenAstVisitor ( C4AulScriptFunc func)
inlineexplicit

Definition at line 268 of file C4AulCompiler.cpp.

References C4AulCompiler::PreparseAstVisitor::visit().

268 : Fn(func), target_host(func->pOrgScript), host(target_host) {}
C4ScriptHost * pOrgScript
Here is the call graph for this function:

◆ ~CodegenAstVisitor()

C4AulCompiler::CodegenAstVisitor::~CodegenAstVisitor ( )
overridedefault

Member Function Documentation

◆ EmitFunctionCode()

template<class T >
void C4AulCompiler::CodegenAstVisitor::EmitFunctionCode ( const T *  n)
inline

Definition at line 304 of file C4AulCompiler.cpp.

Referenced by C4AulCompiler::Compile(), and C4AulCompiler::ConstexprEvaluator::visit().

305  {
306  // This dynamic_cast resolves the problem where we have a Function*
307  // and want to emit code to it. All classes derived from Function
308  // are also ultimately derived from Node, so this call is fine
309  // without any additional checking.
310  EmitFunctionCode(n, dynamic_cast<const ::aul::ast::Node*>(n));
311  }
Here is the caller graph for this function:

◆ visit() [1/32]

virtual void aul::AstVisitor::visit ( const ::aul::ast::IncludePragma )
inlinevirtualinherited

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 91 of file C4AulAST.h.

91 {}

◆ visit() [2/32]

virtual void aul::AstVisitor::visit ( const ::aul::ast::AppendtoPragma )
inlinevirtualinherited

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 92 of file C4AulAST.h.

92 {}

◆ visit() [3/32]

template<class T >
void aul::AstVisitor::visit ( const T *  )
deleteinherited

◆ visit() [4/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Noop )
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 985 of file C4AulCompiler.cpp.

Referenced by C4AulCompiler::Compile().

985 {}
Here is the caller graph for this function:

◆ visit() [5/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::StringLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 987 of file C4AulCompiler.cpp.

References AB_STRING, C4V_String, C4StringTable::RegString(), and Strings.

988 {
989  StackGuard g(this, 1);
990  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(n->value.c_str()));
991  type_of_stack_top = C4V_String;
992 }
C4String * RegString(StdStrBuf String)
C4StringTable Strings
Definition: C4Globals.cpp:42
std::string value
Definition: C4AulAST.h:157
const char * loc
Definition: C4AulAST.h:123
Here is the call graph for this function:

◆ visit() [6/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::IntLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 994 of file C4AulCompiler.cpp.

References AB_INT, and C4V_Int.

995 {
996  StackGuard g(this, 1);
997  AddBCC(n->loc, AB_INT, n->value);
998  type_of_stack_top = C4V_Int;
999 }
uint32_t value
Definition: C4AulAST.h:165
const char * loc
Definition: C4AulAST.h:123

◆ visit() [7/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::BoolLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1001 of file C4AulCompiler.cpp.

References AB_BOOL, and C4V_Bool.

1002 {
1003  StackGuard g(this, 1);
1004  AddBCC(n->loc, AB_BOOL, n->value);
1005  type_of_stack_top = C4V_Bool;
1006 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [8/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ArrayLit n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1008 of file C4AulCompiler.cpp.

References AB_NEW_ARRAY, and C4V_Array.

1009 {
1010  StackGuard g(this, 1);
1011  for (const auto &e : n->values)
1012  {
1013  SafeVisit(e);
1014  }
1015  AddBCC(n->loc, AB_NEW_ARRAY, n->values.size());
1016  type_of_stack_top = C4V_Array;
1017 }
std::vector< ExprPtr > values
Definition: C4AulAST.h:180
const char * loc
Definition: C4AulAST.h:123

◆ visit() [9/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ProplistLit n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1019 of file C4AulCompiler.cpp.

References AB_NEW_PROPLIST, AB_STRING, C4V_PropList, C4StringTable::RegString(), and Strings.

1020 {
1021  StackGuard g(this, 1);
1022  for (const auto &e : n->values)
1023  {
1024  StackGuard g(this, 2);
1025  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(e.first.c_str()));
1026  SafeVisit(e.second);
1027  }
1028  AddBCC(n->loc, AB_NEW_PROPLIST, n->values.size());
1029  type_of_stack_top = C4V_PropList;
1030 }
C4String * RegString(StdStrBuf String)
C4StringTable Strings
Definition: C4Globals.cpp:42
const char * loc
Definition: C4AulAST.h:123
std::vector< std::pair< std::string, ExprPtr > > values
Definition: C4AulAST.h:187
Here is the call graph for this function:

◆ visit() [10/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::NilLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1032 of file C4AulCompiler.cpp.

References AB_NIL, and C4V_Nil.

1033 {
1034  StackGuard g(this, 1);
1035  AddBCC(n->loc, AB_NIL);
1036  type_of_stack_top = C4V_Nil;
1037 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [11/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ThisLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1039 of file C4AulCompiler.cpp.

References AB_THIS, and C4V_PropList.

1040 {
1041  StackGuard g(this, 1);
1042  AddBCC(n->loc, AB_THIS);
1043  type_of_stack_top = C4V_PropList;
1044 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [12/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::VarExpr n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1046 of file C4AulCompiler.cpp.

References C4Value::_getArray(), C4Value::_getBool(), C4Value::_getFunction(), C4Value::_getInt(), C4Value::_getPropList(), C4Value::_getStr(), AB_BOOL, AB_CARRAY, AB_CFUNCTION, AB_CPROPLIST, AB_DUP, AB_GLOBALN, AB_INT, AB_LOCALN, AB_NIL, AB_STRING, C4V_Any, C4V_Array, C4V_Bool, C4V_Function, C4V_Int, C4V_Nil, C4V_PropList, C4V_String, ENSURE_COND, C4StringTable::FindString(), C4AulScriptEngine::GetGlobalConstant(), C4ValueMapNames::GetItemNr(), C4Value::GetType(), C4AulScriptEngine::GlobalConstNames, C4AulScriptEngine::GlobalNamedNames, ScriptEngine, and Strings.

1047 {
1048  StackGuard g(this, 1);
1049  assert(Fn);
1050  C4Value dummy;
1051  const char *cname = n->identifier.c_str();
1052  C4String *interned = ::Strings.FindString(cname);
1053 
1054  // Reset known type of top of value stack so we don't keep the old one around
1055  type_of_stack_top = C4V_Any;
1056 
1057  // Lookup order: Parameters > var > local > global > global const
1058  // Why parameters are considered before function-scoped variables
1059  // you ask? I've no idea, but that's how it was before I started
1060  // changing things.
1061  // NOTE: If you change this, remember to also change the warning
1062  // (variable_shadows_variable) in PreparseAstVisitor.
1063  if (Fn->ParNamed.GetItemNr(cname) != -1)
1064  {
1065  int pos = Fn->ParNamed.GetItemNr(cname);
1066  AddVarAccess(n->loc, AB_DUP, -Fn->GetParCount() + pos);
1067  type_of_stack_top = Fn->GetParType()[pos];
1068  }
1069  else if (Fn->VarNamed.GetItemNr(cname) != -1)
1070  {
1071  AddVarAccess(n->loc, AB_DUP, Fn->VarNamed.GetItemNr(cname));
1072  }
1073  // Can't use Fn->Parent->HasProperty here because that only returns true
1074  // for immediate properties, while we also want to interrogate prototypes
1075  else if (Fn->Parent && interned && Fn->Parent->GetPropertyByS(interned, &dummy))
1076  {
1077  AddBCC(n->loc, AB_LOCALN, (intptr_t)interned);
1078  }
1079  else if (ScriptEngine.GlobalNamedNames.GetItemNr(cname) != -1)
1080  {
1082  }
1083  else if (ScriptEngine.GlobalConstNames.GetItemNr(cname) != -1)
1084  {
1085  C4Value v;
1086  ENSURE_COND(ScriptEngine.GetGlobalConstant(cname, &v), "internal error: global constant not retrievable");
1087  switch (v.GetType())
1088  {
1089  case C4V_Nil:
1090  AddBCC(n->loc, AB_NIL);
1091  break;
1092  case C4V_Int:
1093  AddBCC(n->loc, AB_INT, v._getInt());
1094  break;
1095  case C4V_Bool:
1096  AddBCC(n->loc, AB_BOOL, v._getBool());
1097  break;
1098  case C4V_PropList:
1099  AddBCC(n->loc, AB_CPROPLIST, reinterpret_cast<intptr_t>(v._getPropList()));
1100  break;
1101  case C4V_String:
1102  AddBCC(n->loc, AB_STRING, reinterpret_cast<intptr_t>(v._getStr()));
1103  break;
1104  case C4V_Array:
1105  AddBCC(n->loc, AB_CARRAY, reinterpret_cast<intptr_t>(v._getArray()));
1106  break;
1107  case C4V_Function:
1108  AddBCC(n->loc, AB_CFUNCTION, reinterpret_cast<intptr_t>(v._getFunction()));
1109  default:
1110  AddBCC(n->loc, AB_NIL);
1111  throw Error(target_host, host, n, Fn, "internal error: global constant of unexpected type: %s (of type %s)", cname, v.GetTypeName());
1112  }
1113  type_of_stack_top = v.GetType();
1114  }
1115  else
1116  {
1117  AddBCC(n->loc, AB_NIL);
1118  throw Error(target_host, host, n, Fn, "symbol not found in any symbol table: %s", cname);
1119  }
1120 }
const char * GetTypeName() const
Definition: C4Value.h:164
C4ValueMapNames GlobalNamedNames
Definition: C4Aul.h:134
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
C4ValueMapNames ParNamed
bool GetGlobalConstant(const char *szName, C4Value *pTargetValue)
Definition: C4Aul.cpp:133
C4AulFunc * _getFunction() const
Definition: C4Value.h:128
#define ENSURE_COND(cond, failmsg)
C4ValueMapNames GlobalConstNames
Definition: C4Aul.h:141
C4PropList * _getPropList() const
Definition: C4Value.h:129
C4V_Type GetType() const
Definition: C4Value.h:161
int GetParCount() const override
C4StringTable Strings
Definition: C4Globals.cpp:42
C4ValueMapNames VarNamed
int32_t _getInt() const
Definition: C4Value.h:122
bool _getBool() const
Definition: C4Value.h:123
C4ValueArray * _getArray() const
Definition: C4Value.h:127
const C4V_Type * GetParType() const override
const char * loc
Definition: C4AulAST.h:123
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459
C4String * FindString(const char *strString) const
std::string identifier
Definition: C4AulAST.h:205
C4PropListStatic * Parent
Definition: C4AulFunc.h:55
C4String * _getStr() const
Definition: C4Value.h:126
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:757
Here is the call graph for this function:

◆ visit() [13/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::UnOpExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1122 of file C4AulCompiler.cpp.

References AB_Dec, AB_Inc, and C4ScriptOpMap.

1123 {
1124  StackGuard g(this, 1);
1125 
1126  n->operand->accept(this);
1127  const auto &op = C4ScriptOpMap[n->op];
1128  if (op.Changer)
1129  {
1130  C4AulBCC setter = MakeSetter(n->loc, true);
1131  AddBCC(n->loc, op.Code, 0);
1132  AddBCC(n->loc, setter);
1133  // On postfix inc/dec, regenerate the previous value
1134  if (op.Postfix && (op.Code == AB_Inc || op.Code == AB_Dec))
1135  {
1136  AddBCC(n->loc, op.Code == AB_Inc ? AB_Dec : AB_Inc, 1);
1137  }
1138  }
1139  else
1140  {
1141  AddBCC(n->loc, op.Code);
1142  }
1143  type_of_stack_top = op.RetType;
1144 }
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:274
const char * loc
Definition: C4AulAST.h:123

◆ visit() [14/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::BinOpExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1146 of file C4AulCompiler.cpp.

References AB_JUMPAND, AB_JUMPNNIL, AB_JUMPOR, and C4ScriptOpMap.

1147 {
1148  StackGuard g(this, 1);
1149 
1150  SafeVisit(n->lhs);
1151 
1152  const auto &op = C4ScriptOpMap[n->op];
1153  if (op.Code == AB_JUMPAND || op.Code == AB_JUMPOR || op.Code == AB_JUMPNNIL)
1154  {
1155  // Short-circuiting operators. These are slightly more complex
1156  // because we don't want to evaluate their rhs operand when the
1157  // lhs one already decided the result
1158  int jump = AddBCC(n->loc, op.Code);
1159  SafeVisit(n->rhs);
1160  UpdateJump(jump, AddJumpTarget());
1161  }
1162  else if (op.Changer)
1163  {
1164  try
1165  {
1166  C4AulBCC setter = MakeSetter(n->loc, true);
1167  SafeVisit(n->rhs);
1168  AddBCC(n->loc, op.Code);
1169  AddBCC(n->loc, setter);
1170  }
1171  catch (C4AulParseError &e)
1172  {
1173  HandleError(e);
1174  }
1175  }
1176  else
1177  {
1178  SafeVisit(n->rhs);
1179  AddBCC(n->loc, op.Code, 0);
1180  }
1181 
1182  type_of_stack_top = op.RetType;
1183 }
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:274
const char * loc
Definition: C4AulAST.h:123

◆ visit() [15/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::AssignmentExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1185 of file C4AulCompiler.cpp.

1186 {
1187  StackGuard g(this, 1);
1188  SafeVisit(n->lhs);
1189  try
1190  {
1191  C4AulBCC setter = MakeSetter(n->loc, false);
1192  SafeVisit(n->rhs);
1193  AddBCC(n->loc, setter);
1194  }
1195  catch (C4AulParseError &e)
1196  {
1197  HandleError(e);
1198  }
1199  // Assignment does not change the type of the variable
1200 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [16/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::SubscriptExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1202 of file C4AulCompiler.cpp.

References AB_ARRAYA, and C4V_Any.

1203 {
1204  StackGuard g(this, 1);
1205  SafeVisit(n->object);
1206  SafeVisit(n->index);
1207  AddBCC(n->loc, AB_ARRAYA);
1208 
1209  // FIXME: Check if the subscripted object is a literal and if so, retrieve type
1210  type_of_stack_top = C4V_Any;
1211 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [17/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::SliceExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1213 of file C4AulCompiler.cpp.

References AB_ARRAY_SLICE, and C4V_Array.

1214 {
1215  StackGuard g(this, 1);
1216  SafeVisit(n->object);
1217  SafeVisit(n->start);
1218  SafeVisit(n->end);
1219  AddBCC(n->loc, AB_ARRAY_SLICE);
1220 
1221  type_of_stack_top = C4V_Array;
1222 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [18/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::CallExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1224 of file C4AulCompiler.cpp.

References C4AUL_DebugBreak.

1225 {
1226  const char *cname = n->callee.c_str();
1227 
1228  if (n->callee == C4AUL_DebugBreak)
1229  {
1230  if (n->context)
1231  throw Error(target_host, host, n, Fn, R"("%s" can't be called in a different context)", cname);
1232  if (!n->args.empty())
1233  throw Error(target_host, host, n, Fn, R"("%s" must not have any arguments)", cname);
1234 
1235  AddBCC(n->loc, AB_DEBUG);
1236  // Add a pseudo-nil to keep the stack balanced
1237  AddBCC(n->loc, AB_NIL);
1238  type_of_stack_top = C4V_Nil;
1239  return;
1240  }
1241 
1242  if (n->callee == C4AUL_Inherited || n->callee == C4AUL_SafeInherited)
1243  {
1244  // inherited can only be called within the same context
1245  if (n->context)
1246  {
1247  throw Error(target_host, host, n, Fn, R"("%s" can't be called in a different context)", cname);
1248  }
1249  }
1250 
1251  if (n->callee == C4AUL_Inherited && !Fn->OwnerOverloaded)
1252  {
1253  throw Error(target_host, host, n, Fn, "inherited function not found (use " C4AUL_SafeInherited " to disable this message)");
1254  }
1255 
1256  const auto pre_call_stack = stack_height;
1257 
1258  if (n->context)
1259  SafeVisit(n->context);
1260 
1261  std::vector<C4V_Type> known_par_types;
1262  known_par_types.reserve(n->args.size());
1263 
1264  for (const auto &arg : n->args)
1265  {
1266  SafeVisit(arg);
1267  known_par_types.push_back(type_of_stack_top);
1268  }
1269 
1270  C4AulFunc *callee = nullptr;
1271 
1272  // Special handling for the overload chain
1273  if (n->callee == C4AUL_Inherited || n->callee == C4AUL_SafeInherited)
1274  {
1275  callee = Fn->OwnerOverloaded;
1276  }
1277 
1278  size_t fn_argc = C4AUL_MAX_Par;
1279  if (!n->context)
1280  {
1281  // if this is a function without explicit context, we resolve it
1282  if (!callee)
1283  callee = Fn->Parent->GetFunc(cname);
1284  if (!callee && target_host)
1285  callee = target_host->Engine->GetFunc(cname);
1286 
1287  if (callee)
1288  {
1289  fn_argc = callee->GetParCount();
1290  }
1291  else
1292  {
1293  // pop all args off the stack
1294  if (!n->args.empty())
1295  AddBCC(n->loc, AB_STACK, -(intptr_t)n->args.size());
1296  // and "return" nil
1297  AddBCC(n->loc, AB_NIL);
1298  type_of_stack_top = C4V_Nil;
1299 
1300  if (n->callee != C4AUL_SafeInherited)
1301  {
1302  HandleError(Error(target_host, host, n, Fn, "called function not found: %s", cname));
1303  }
1304  return;
1305  }
1306  }
1307 
1308  if (n->args.size() > fn_argc)
1309  {
1310  // Pop off any args that are over the limit
1311  Warn(target_host, host, n->args[fn_argc].get(), Fn, C4AulWarningId::arg_count_mismatch,
1312  cname, (unsigned)n->args.size(), fn_argc);
1313  AddBCC(n->loc, AB_STACK, fn_argc - n->args.size());
1314  }
1315  else if (n->args.size() < fn_argc)
1316  {
1317  if (n->append_unnamed_pars)
1318  {
1319  assert(Fn->GetParCount() == C4AUL_MAX_Par);
1320  int missing_par_count = fn_argc - n->args.size();
1321  int available_par_count = Fn->GetParCount() - Fn->ParNamed.iSize;
1322  for (int i = 0; i < std::min(missing_par_count, available_par_count); ++i)
1323  {
1324  AddVarAccess(n->loc, AB_DUP, -Fn->GetParCount() + Fn->ParNamed.iSize + i);
1325  }
1326  // Fill up remaining, unsettable parameters with nil
1327  if (available_par_count < missing_par_count)
1328  AddBCC(n->loc, AB_STACK, missing_par_count - available_par_count);
1329  }
1330  else if (fn_argc > n->args.size())
1331  {
1332  // Add nil for each missing parameter
1333  AddBCC(n->loc, AB_STACK, fn_argc - n->args.size());
1334  }
1335  }
1336 
1337  // Check passed parameters for this call (as far as possible)
1338  std::vector<C4V_Type> expected_par_types;
1339  if (n->context)
1340  {
1341  AddBCC(n->loc, n->safe_call ? AB_CALLFS : AB_CALL, (intptr_t)::Strings.RegString(cname));
1342  // Since we don't know the context in which this call will happen at
1343  // runtime, we'll check whether all available functions with the same
1344  // name agree on their parameters.
1345  const C4AulFunc *candidate = target_host ? target_host->Engine->GetFirstFunc(cname) : nullptr;
1346  if (candidate)
1347  {
1348  expected_par_types.assign(candidate->GetParType(), candidate->GetParType() + candidate->GetParCount());
1349  while ((candidate = target_host->Engine->GetNextSNFunc(candidate)) != nullptr)
1350  {
1351  if (candidate->GetParCount() > expected_par_types.size())
1352  {
1353  expected_par_types.resize(candidate->GetParCount(), C4V_Any);
1354  }
1355  for (size_t i = 0; i < expected_par_types.size(); ++i)
1356  {
1357  C4V_Type a = expected_par_types[i];
1358  C4V_Type b = candidate->GetParType()[i];
1359  // If we can convert one of the types into the other
1360  // without a warning, use the wider one
1361  bool implicit_a_to_b = !C4Value::WarnAboutConversion(a, b);
1362  bool implicit_b_to_a = !C4Value::WarnAboutConversion(b, a);
1363  if (implicit_a_to_b && !implicit_b_to_a)
1364  expected_par_types[i] = b;
1365  else if (implicit_b_to_a && !implicit_a_to_b)
1366  expected_par_types[i] = a;
1367  // but if we can convert neither of the types into the
1368  // other, give up and assume the user will do the right
1369  // thing
1370  else if (!implicit_a_to_b && !implicit_b_to_a)
1371  expected_par_types[i] = C4V_Any;
1372  }
1373  }
1374  }
1375  type_of_stack_top = C4V_Any;
1376  }
1377  else
1378  {
1379  assert(callee);
1380  AddBCC(n->loc, AB_FUNC, (intptr_t)callee);
1381  expected_par_types.assign(callee->GetParType(), callee->GetParType() + callee->GetParCount());
1382  type_of_stack_top = callee->GetRetType();
1383  }
1384 
1385  // Check parameters
1386  for (size_t i = 0; i < std::min(known_par_types.size(), expected_par_types.size()); ++i)
1387  {
1388  C4V_Type from = known_par_types[i];
1389  C4V_Type to = expected_par_types[i];
1390  if (C4Value::WarnAboutConversion(from, to))
1391  {
1392  Warn(target_host, host, n->args[i].get(), Fn, C4AulWarningId::arg_type_mismatch, (unsigned)i, cname, GetC4VName(from), GetC4VName(to));
1393  }
1394  }
1395 
1396  // We leave one value (the return value) on the stack
1397  assert(pre_call_stack + 1 == stack_height);
1398 }
virtual int GetParCount() const
Definition: C4AulFunc.h:69
C4V_Type
Definition: C4Value.h:23
#define C4AUL_Inherited
C4ValueMapNames ParNamed
#define b
C4String * RegString(StdStrBuf String)
bool append_unnamed_pars
Definition: C4AulAST.h:255
std::string callee
Definition: C4AulAST.h:258
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:76
#define a
virtual const C4V_Type * GetParType() const =0
std::vector< ExprPtr > args
Definition: C4AulAST.h:257
C4AulFunc * OwnerOverloaded
C4AulFunc * GetFirstFunc(const char *Name)
Definition: C4Aul.h:117
int GetParCount() const override
#define C4AUL_MAX_Par
Definition: C4AulFunc.h:26
C4AulFunc * GetNextSNFunc(const C4AulFunc *After)
Definition: C4Aul.h:119
C4StringTable Strings
Definition: C4Globals.cpp:42
virtual C4V_Type GetRetType() const =0
static bool WarnAboutConversion(C4V_Type Type, C4V_Type vtToType)
Definition: C4Value.cpp:111
const char * GetC4VName(const C4V_Type Type)
Definition: C4Value.cpp:32
#define C4AUL_DebugBreak
const char * loc
Definition: C4AulAST.h:123
#define C4AUL_SafeInherited
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:105
C4PropListStatic * Parent
Definition: C4AulFunc.h:55

◆ visit() [19/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ParExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1400 of file C4AulCompiler.cpp.

References AB_PAR, and C4V_Any.

1401 {
1402  StackGuard g(this, 1);
1403 
1404  SafeVisit(n->arg);
1405  AddBCC(n->loc, AB_PAR);
1406  type_of_stack_top = C4V_Any;
1407 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [20/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Block n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1409 of file C4AulCompiler.cpp.

References s.

1410 {
1411  for (const auto &s : n->children)
1412  {
1413  StackGuard g(this, 0);
1414  if (SafeVisit(s))
1415  {
1416  // If the statement has left a stack value, pop it off
1417  MaybePopValueOf(s);
1418  }
1419  }
1420 }
std::vector< StmtPtr > children
Definition: C4AulAST.h:273
#define s

◆ visit() [21/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Return n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1422 of file C4AulCompiler.cpp.

References AB_RETURN.

1423 {
1424  StackGuard g(this, 0);
1425 
1426  WarnOnAssignment(n->value);
1427  SafeVisit(n->value);
1428  AddBCC(n->loc, AB_RETURN);
1429 }
ExprPtr value
Definition: C4AulAST.h:284
const char * loc
Definition: C4AulAST.h:123

◆ visit() [22/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ForLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1431 of file C4AulCompiler.cpp.

References AB_CONDN, and AB_JUMP.

1432 {
1433  // Bytecode arranged like this:
1434  // initializer
1435  // cond: condition
1436  // CONDN exit
1437  // body: body
1438  // incr: incrementor
1439  // JUMP cond
1440  // exit:
1441  //
1442  // continue jumps to incr
1443  // break jumps to exit
1444 
1445  if (n->init)
1446  {
1447  if (SafeVisit(n->init))
1448  MaybePopValueOf(n->init);
1449  }
1450  int cond = -1, condition_jump = -1;
1451  PushLoop();
1452  if (n->cond)
1453  {
1454  WarnOnAssignment(n->cond);
1455  cond = AddJumpTarget();
1456  SafeVisit(n->cond);
1457  active_loops.top().breaks.push_back(AddBCC(n->cond->loc, AB_CONDN));
1458  }
1459 
1460  int body = AddJumpTarget();
1461  if (!n->cond)
1462  cond = body;
1463  if (SafeVisit(n->body))
1464  MaybePopValueOf(n->body);
1465 
1466  int incr = -1;
1467  if (n->incr)
1468  {
1469  incr = AddJumpTarget();
1470  if (SafeVisit(n->incr))
1471  MaybePopValueOf(n->incr);
1472  }
1473  else
1474  {
1475  // If no incrementor exists, just jump straight to the condition
1476  incr = cond;
1477  }
1478  // start the next iteration of the loop
1479  AddJumpTo(n->loc, AB_JUMP, cond);
1480  PopLoop(incr);
1481 }
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
const char * loc
Definition: C4AulAST.h:123

◆ visit() [23/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::RangeLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1483 of file C4AulCompiler.cpp.

1484 {
1485  // Bytecode arranged like this:
1486  // condition (aka iterated array)
1487  // INT 0 (the loop index variable)
1488  // cond: FOREACH_NEXT
1489  // JUMP exit
1490  // body: body
1491  // JUMP cond
1492  // exit: STACK -2 (to clean the iteration variables)
1493  //
1494  // continue jumps to cond
1495  // break jumps to exit
1496 
1497  const char *cname = n->var.c_str();
1498  int var_id = Fn->VarNamed.GetItemNr(cname);
1499  assert(var_id != -1 && "CodegenAstVisitor: unable to find variable in foreach");
1500  if (var_id == -1)
1501  throw Error(target_host, host, n, Fn, "internal error: unable to find variable in foreach: %s", cname);
1502  // Emit code for array
1503  SafeVisit(n->cond);
1504  // Emit code for iteration
1505  AddBCC(n->loc, AB_INT, 0);
1506  int cond = AddJumpTarget();
1507  PushLoop();
1508  AddVarAccess(n->loc, AB_FOREACH_NEXT, var_id);
1509  AddLoopControl(n->loc, Loop::Control::Break); // Will be skipped by AB_FOREACH_NEXT as long as more entries exist
1510 
1511  // Emit body
1512  if (SafeVisit(n->body))
1513  MaybePopValueOf(n->body);
1514  // continue starts the next iteration of the loop
1515  AddLoopControl(n->loc, Loop::Control::Continue);
1516  PopLoop(cond);
1517  // Pop off iterator and array
1518  AddBCC(n->loc, AB_STACK, -2);
1519 }
std::string var
Definition: C4AulAST.h:307
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
C4ValueMapNames VarNamed
const char * loc
Definition: C4AulAST.h:123
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459

◆ visit() [24/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::DoLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1557 of file C4AulCompiler.cpp.

References AB_COND.

1558 {
1559  int body = AddJumpTarget();
1560  PushLoop();
1561  if (SafeVisit(n->body))
1562  MaybePopValueOf(n->body);
1563  int cond = AddJumpTarget();
1564  SafeVisit(n->cond);
1565  AddJumpTo(n->loc, AB_COND, body);
1566  PopLoop(cond);
1567 }
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
const char * loc
Definition: C4AulAST.h:123

◆ visit() [25/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::WhileLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1569 of file C4AulCompiler.cpp.

References AB_CONDN.

1570 {
1571  int cond = AddJumpTarget();
1572  PushLoop();
1573  // XXX:
1574  // Assignments in the condition here should warn as well (like they do in
1575  // for and if conditions) but a ton of code uses those assignments at the
1576  // moment and people are divided about allowing it
1577  SafeVisit(n->cond);
1578  active_loops.top().breaks.push_back(AddBCC(n->cond->loc, AB_CONDN));
1579  if (SafeVisit(n->body))
1580  MaybePopValueOf(n->body);
1581  // continue starts the next iteration of the loop
1582  AddLoopControl(n->loc, Loop::Control::Continue);
1583  PopLoop(cond);
1584 }
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
const char * loc
Definition: C4AulAST.h:123

◆ visit() [26/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Break n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1586 of file C4AulCompiler.cpp.

References ENSURE_COND.

1587 {
1588  ENSURE_COND(!active_loops.empty(), "'break' outside loop");
1589  AddLoopControl(n->loc, Loop::Control::Break);
1590 }
#define ENSURE_COND(cond, failmsg)
const char * loc
Definition: C4AulAST.h:123

◆ visit() [27/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Continue n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1592 of file C4AulCompiler.cpp.

References ENSURE_COND.

1593 {
1594  ENSURE_COND(!active_loops.empty(), "'continue' outside loop");
1595  AddLoopControl(n->loc, Loop::Control::Continue);
1596 }
#define ENSURE_COND(cond, failmsg)
const char * loc
Definition: C4AulAST.h:123

◆ visit() [28/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::If n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1598 of file C4AulCompiler.cpp.

References AB_CONDN.

1599 {
1600  WarnOnAssignment(n->cond);
1601  SafeVisit(n->cond);
1602  int jump = AddBCC(n->loc, AB_CONDN);
1603  // Warn if we're controlling a no-op ("if (...);")
1604  if (dynamic_cast<::aul::ast::Noop*>(n->iftrue.get()))
1605  {
1606  Warn(target_host, host, n->iftrue->loc, Fn, C4AulWarningId::empty_if);
1607  }
1608  if (SafeVisit(n->iftrue))
1609  MaybePopValueOf(n->iftrue);
1610 
1611  if (dynamic_cast<::aul::ast::Noop*>(n->iffalse.get()))
1612  {
1613  Warn(target_host, host, n->iffalse->loc, Fn, C4AulWarningId::empty_if);
1614  }
1615 
1616  if (n->iffalse)
1617  {
1618  int jumpout = AddBCC(n->loc, AB_JUMP);
1619  UpdateJump(jump, AddJumpTarget());
1620  jump = jumpout;
1621  if (SafeVisit(n->iffalse))
1622  MaybePopValueOf(n->iffalse);
1623  }
1624  UpdateJump(jump, AddJumpTarget());
1625 }
ExprPtr cond
Definition: C4AulAST.h:338
StmtPtr iftrue
Definition: C4AulAST.h:339
StmtPtr iffalse
Definition: C4AulAST.h:339
const char * loc
Definition: C4AulAST.h:123

◆ visit() [29/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::VarDecl n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1627 of file C4AulCompiler.cpp.

References AB_STACK.

1628 {
1629  for (const auto &dec : n->decls)
1630  {
1631  const char *cname = dec.name.c_str();
1632  switch (n->scope)
1633  {
1634  case ::aul::ast::VarDecl::Scope::Func:
1635  if (dec.init)
1636  {
1637  // Emit code for the initializer
1638  SafeVisit(dec.init);
1639  int var_idx = Fn->VarNamed.GetItemNr(cname);
1640  assert(var_idx >= 0 && "CodegenAstVisitor: var not found in variable table");
1641  if (var_idx < 0)
1642  {
1643  AddBCC(n->loc, AB_STACK, -1);
1644  throw Error(target_host, host, n, Fn, "internal error: var not found in variable table: %s", cname);
1645  }
1646  AddVarAccess(n->loc, AB_POP_TO, var_idx);
1647  }
1648  break;
1650  case ::aul::ast::VarDecl::Scope::Global:
1651  // Object-local and global constants are handled by ConstantResolver.
1652  break;
1653  }
1654  }
1655 }
C4ValueMapNames VarNamed
std::vector< Var > decls
Definition: C4AulAST.h:365
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
const char * loc
Definition: C4AulAST.h:123
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459

◆ visit() [30/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::FunctionDecl n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1657 of file C4AulCompiler.cpp.

1658 {
1659  assert(!Fn && "CodegenAstVisitor: function declaration encountered within active function");
1660  if (Fn)
1661  throw Error(target_host, host, n, Fn, "internal error: function declaration for '%s' encountered within active function", n->name.c_str());
1662 
1663  C4PropListStatic *Parent = n->is_global ? target_host->Engine->GetPropList() : target_host->GetPropList();
1664 
1665  C4String *name = ::Strings.FindString(n->name.c_str());
1666  C4AulFunc *f = Parent->GetFunc(name);
1667  while (f)
1668  {
1669  if (f->SFunc() && f->SFunc()->pOrgScript == host && f->Parent == Parent)
1670  {
1671  if (Fn)
1672  Warn(target_host, host, n, Fn, C4AulWarningId::redeclaration, "function", f->GetName());
1673  Fn = f->SFunc();
1674  }
1675  f = f->SFunc() ? f->SFunc()->OwnerOverloaded : nullptr;
1676  }
1677 
1678  if (!Fn && Parent->HasProperty(name))
1679  {
1680  throw Error(target_host, host, n, Fn, "declaration of '%s': cannot override local variable via 'func %s'", n->name.c_str(), n->name.c_str());
1681  }
1682 
1683  assert(Fn && "CodegenAstVisitor: unable to find function definition");
1684  if (!Fn)
1685  throw Error(target_host, host, n, Fn, "internal error: unable to find function definition for %s", n->name.c_str());
1686 
1687  // If this isn't a global function, but there is a global one with
1688  // the same name, and this function isn't overloading a different
1689  // one, add the global function to the overload chain
1690  if (!n->is_global && !Fn->OwnerOverloaded)
1691  {
1692  C4AulFunc *global_parent = target_host->Engine->GetFunc(Fn->GetName());
1693  if (global_parent)
1694  Fn->SetOverloaded(global_parent);
1695  }
1696 
1697  try
1698  {
1699  EmitFunctionCode(n);
1700  Fn = nullptr;
1701  }
1702  catch (...)
1703  {
1704  Fn = nullptr;
1705  throw;
1706  }
1707 }
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
C4ScriptHost * pOrgScript
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:76
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:50
C4AulFunc * OwnerOverloaded
const char * GetName() const
Definition: C4AulFunc.h:56
C4StringTable Strings
Definition: C4Globals.cpp:42
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:105
std::string name
Definition: C4AulAST.h:390
C4String * FindString(const char *strString) const
C4PropListStatic * Parent
Definition: C4AulFunc.h:55
virtual C4AulScriptFunc * SFunc()
Definition: C4AulFunc.h:65

◆ visit() [31/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::FunctionExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1709 of file C4AulCompiler.cpp.

References AB_NIL.

1710 {
1711  AddBCC(n->loc, AB_NIL);
1712  throw Error(target_host, host, n, Fn, "can't define a function in a function-scoped proplist");
1713 }
const char * loc
Definition: C4AulAST.h:123

◆ visit() [32/32]

void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Script n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1715 of file C4AulCompiler.cpp.

1716 {
1717  for (const auto &d : n->declarations)
1718  {
1719  SafeVisit(d);
1720  }
1721 }
std::vector< DeclPtr > declarations
Definition: C4AulAST.h:425

The documentation for this class was generated from the following file: