OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
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 144 of file C4AulCompiler.cpp.

Constructor & Destructor Documentation

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

Definition at line 253 of file C4AulCompiler.cpp.

253 : target_host(host), host(source_host) {}
C4AulCompiler::CodegenAstVisitor::CodegenAstVisitor ( C4AulScriptFunc func)
inlineexplicit

Definition at line 254 of file C4AulCompiler.cpp.

254 : Fn(func), target_host(func->pOrgScript), host(target_host) {}
C4ScriptHost * pOrgScript
C4AulCompiler::CodegenAstVisitor::~CodegenAstVisitor ( )
overridedefault

Member Function Documentation

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

Definition at line 290 of file C4AulCompiler.cpp.

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

291  {
292  // This dynamic_cast resolves the problem where we have a Function*
293  // and want to emit code to it. All classes derived from Function
294  // are also ultimately derived from Node, so this call is fine
295  // without any additional checking.
296  EmitFunctionCode(n, dynamic_cast<const ::aul::ast::Node*>(n));
297  }

Here is the caller graph for this function:

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

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 91 of file C4AulAST.h.

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

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 92 of file C4AulAST.h.

92 {}
template<class T >
void aul::AstVisitor::visit ( const T *  )
deleteinherited
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Noop )
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 971 of file C4AulCompiler.cpp.

Referenced by C4AulCompiler::Compile().

971 {}

Here is the caller graph for this function:

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

Reimplemented from aul::AstVisitor.

Definition at line 973 of file C4AulCompiler.cpp.

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

974 {
975  StackGuard g(this, 1);
976  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(n->value.c_str()));
977  type_of_stack_top = C4V_String;
978 }
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:

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

Reimplemented from aul::AstVisitor.

Definition at line 980 of file C4AulCompiler.cpp.

References AB_INT, and C4V_Int.

981 {
982  StackGuard g(this, 1);
983  AddBCC(n->loc, AB_INT, n->value);
984  type_of_stack_top = C4V_Int;
985 }
uint32_t value
Definition: C4AulAST.h:165
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::BoolLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 987 of file C4AulCompiler.cpp.

References AB_BOOL, and C4V_Bool.

988 {
989  StackGuard g(this, 1);
990  AddBCC(n->loc, AB_BOOL, n->value);
991  type_of_stack_top = C4V_Bool;
992 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ArrayLit n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 994 of file C4AulCompiler.cpp.

References AB_NEW_ARRAY, and C4V_Array.

995 {
996  StackGuard g(this, 1);
997  for (const auto &e : n->values)
998  {
999  SafeVisit(e);
1000  }
1001  AddBCC(n->loc, AB_NEW_ARRAY, n->values.size());
1002  type_of_stack_top = C4V_Array;
1003 }
std::vector< ExprPtr > values
Definition: C4AulAST.h:180
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ProplistLit n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1005 of file C4AulCompiler.cpp.

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

1006 {
1007  StackGuard g(this, 1);
1008  for (const auto &e : n->values)
1009  {
1010  StackGuard g(this, 2);
1011  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(e.first.c_str()));
1012  SafeVisit(e.second);
1013  }
1014  AddBCC(n->loc, AB_NEW_PROPLIST, n->values.size());
1015  type_of_stack_top = C4V_PropList;
1016 }
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:

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

Reimplemented from aul::AstVisitor.

Definition at line 1018 of file C4AulCompiler.cpp.

References AB_NIL, and C4V_Nil.

1019 {
1020  StackGuard g(this, 1);
1021  AddBCC(n->loc, AB_NIL);
1022  type_of_stack_top = C4V_Nil;
1023 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ThisLit n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1025 of file C4AulCompiler.cpp.

References AB_THIS, and C4V_PropList.

1026 {
1027  StackGuard g(this, 1);
1028  AddBCC(n->loc, AB_THIS);
1029  type_of_stack_top = C4V_PropList;
1030 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::VarExpr n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1032 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(), C4Value::GetTypeName(), C4AulScriptEngine::GlobalConstNames, C4AulScriptEngine::GlobalNamedNames, ScriptEngine, and Strings.

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

Here is the call graph for this function:

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1108 of file C4AulCompiler.cpp.

References AB_Dec, AB_Inc, and C4ScriptOpMap.

1109 {
1110  StackGuard g(this, 1);
1111 
1112  n->operand->accept(this);
1113  const auto &op = C4ScriptOpMap[n->op];
1114  if (op.Changer)
1115  {
1116  C4AulBCC setter = MakeSetter(n->loc, true);
1117  AddBCC(n->loc, op.Code, 0);
1118  AddBCC(n->loc, setter);
1119  // On postfix inc/dec, regenerate the previous value
1120  if (op.Postfix && (op.Code == AB_Inc || op.Code == AB_Dec))
1121  {
1122  AddBCC(n->loc, op.Code == AB_Inc ? AB_Dec : AB_Inc, 1);
1123  }
1124  }
1125  else
1126  {
1127  AddBCC(n->loc, op.Code);
1128  }
1129  type_of_stack_top = op.RetType;
1130 }
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:261
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::BinOpExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1132 of file C4AulCompiler.cpp.

References AB_JUMPAND, AB_JUMPNNIL, AB_JUMPOR, and C4ScriptOpMap.

1133 {
1134  StackGuard g(this, 1);
1135 
1136  SafeVisit(n->lhs);
1137 
1138  const auto &op = C4ScriptOpMap[n->op];
1139  if (op.Code == AB_JUMPAND || op.Code == AB_JUMPOR || op.Code == AB_JUMPNNIL)
1140  {
1141  // Short-circuiting operators. These are slightly more complex
1142  // because we don't want to evaluate their rhs operand when the
1143  // lhs one already decided the result
1144  int jump = AddBCC(n->loc, op.Code);
1145  SafeVisit(n->rhs);
1146  UpdateJump(jump, AddJumpTarget());
1147  }
1148  else if (op.Changer)
1149  {
1150  try
1151  {
1152  C4AulBCC setter = MakeSetter(n->loc, true);
1153  SafeVisit(n->rhs);
1154  AddBCC(n->loc, op.Code);
1155  AddBCC(n->loc, setter);
1156  }
1157  catch (C4AulParseError &e)
1158  {
1159  HandleError(e);
1160  }
1161  }
1162  else
1163  {
1164  SafeVisit(n->rhs);
1165  AddBCC(n->loc, op.Code, 0);
1166  }
1167 
1168  type_of_stack_top = op.RetType;
1169 }
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:261
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::AssignmentExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1171 of file C4AulCompiler.cpp.

1172 {
1173  StackGuard g(this, 1);
1174  SafeVisit(n->lhs);
1175  try
1176  {
1177  C4AulBCC setter = MakeSetter(n->loc, false);
1178  SafeVisit(n->rhs);
1179  AddBCC(n->loc, setter);
1180  }
1181  catch (C4AulParseError &e)
1182  {
1183  HandleError(e);
1184  }
1185  // Assignment does not change the type of the variable
1186 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::SubscriptExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1188 of file C4AulCompiler.cpp.

References AB_ARRAYA, and C4V_Any.

1189 {
1190  StackGuard g(this, 1);
1191  SafeVisit(n->object);
1192  SafeVisit(n->index);
1193  AddBCC(n->loc, AB_ARRAYA);
1194 
1195  // FIXME: Check if the subscripted object is a literal and if so, retrieve type
1196  type_of_stack_top = C4V_Any;
1197 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::SliceExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1199 of file C4AulCompiler.cpp.

References AB_ARRAY_SLICE, and C4V_Array.

1200 {
1201  StackGuard g(this, 1);
1202  SafeVisit(n->object);
1203  SafeVisit(n->start);
1204  SafeVisit(n->end);
1205  AddBCC(n->loc, AB_ARRAY_SLICE);
1206 
1207  type_of_stack_top = C4V_Array;
1208 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::CallExpr n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1210 of file C4AulCompiler.cpp.

References a, AB_CALL, AB_CALLFS, AB_DEBUG, AB_DUP, AB_FUNC, AB_NIL, AB_STACK, b, C4AUL_DebugBreak, C4AUL_Inherited, C4AUL_MAX_Par, C4AUL_SafeInherited, C4V_Any, C4V_Nil, C4ScriptHost::Engine, GetC4VName(), C4AulScriptEngine::GetFirstFunc(), C4PropList::GetFunc(), C4AulScriptEngine::GetNextSNFunc(), C4AulFunc::GetParCount(), C4AulFunc::Parent, C4StringTable::RegString(), Strings, and C4Value::WarnAboutConversion().

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

Here is the call graph for this function:

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1386 of file C4AulCompiler.cpp.

References AB_PAR, and C4V_Any.

1387 {
1388  StackGuard g(this, 1);
1389 
1390  SafeVisit(n->arg);
1391  AddBCC(n->loc, AB_PAR);
1392  type_of_stack_top = C4V_Any;
1393 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Block n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1395 of file C4AulCompiler.cpp.

References s.

1396 {
1397  for (const auto &s : n->children)
1398  {
1399  StackGuard g(this, 0);
1400  if (SafeVisit(s))
1401  {
1402  // If the statement has left a stack value, pop it off
1403  MaybePopValueOf(s);
1404  }
1405  }
1406 }
std::vector< StmtPtr > children
Definition: C4AulAST.h:273
#define s
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Return n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1408 of file C4AulCompiler.cpp.

References AB_RETURN.

1409 {
1410  StackGuard g(this, 0);
1411 
1412  SafeVisit(n->value);
1413  AddBCC(n->loc, AB_RETURN);
1414 }
ExprPtr value
Definition: C4AulAST.h:284
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::ForLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1416 of file C4AulCompiler.cpp.

References AB_CONDN, and AB_JUMP.

1417 {
1418  // Bytecode arranged like this:
1419  // initializer
1420  // cond: condition
1421  // CONDN exit
1422  // body: body
1423  // incr: incrementor
1424  // JUMP cond
1425  // exit:
1426  //
1427  // continue jumps to incr
1428  // break jumps to exit
1429 
1430  if (n->init)
1431  {
1432  if (SafeVisit(n->init))
1433  MaybePopValueOf(n->init);
1434  }
1435  int cond = -1, condition_jump = -1;
1436  PushLoop();
1437  if (n->cond)
1438  {
1439  cond = AddJumpTarget();
1440  SafeVisit(n->cond);
1441  active_loops.top().breaks.push_back(AddBCC(n->cond->loc, AB_CONDN));
1442  }
1443 
1444  int body = AddJumpTarget();
1445  if (!n->cond)
1446  cond = body;
1447  if (SafeVisit(n->body))
1448  MaybePopValueOf(n->body);
1449 
1450  int incr = -1;
1451  if (n->incr)
1452  {
1453  incr = AddJumpTarget();
1454  if (SafeVisit(n->incr))
1455  MaybePopValueOf(n->incr);
1456  }
1457  else
1458  {
1459  // If no incrementor exists, just jump straight to the condition
1460  incr = cond;
1461  }
1462  // start the next iteration of the loop
1463  AddJumpTo(n->loc, AB_JUMP, cond);
1464  PopLoop(incr);
1465 }
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::RangeLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1467 of file C4AulCompiler.cpp.

References AB_FOREACH_NEXT, AB_INT, and AB_STACK.

1468 {
1469  // Bytecode arranged like this:
1470  // condition (aka iterated array)
1471  // INT 0 (the loop index variable)
1472  // cond: FOREACH_NEXT
1473  // JUMP exit
1474  // body: body
1475  // JUMP cond
1476  // exit: STACK -2 (to clean the iteration variables)
1477  //
1478  // continue jumps to cond
1479  // break jumps to exit
1480 
1481  const char *cname = n->var.c_str();
1482  int var_id = Fn->VarNamed.GetItemNr(cname);
1483  assert(var_id != -1 && "CodegenAstVisitor: unable to find variable in foreach");
1484  if (var_id == -1)
1485  throw Error(target_host, host, n, Fn, "internal error: unable to find variable in foreach: %s", cname);
1486  // Emit code for array
1487  SafeVisit(n->cond);
1488  // Emit code for iteration
1489  AddBCC(n->loc, AB_INT, 0);
1490  int cond = AddJumpTarget();
1491  PushLoop();
1492  AddVarAccess(n->loc, AB_FOREACH_NEXT, var_id);
1493  AddLoopControl(n->loc, Loop::Control::Break); // Will be skipped by AB_FOREACH_NEXT as long as more entries exist
1494 
1495  // Emit body
1496  if (SafeVisit(n->body))
1497  MaybePopValueOf(n->body);
1498  // continue starts the next iteration of the loop
1499  AddLoopControl(n->loc, Loop::Control::Continue);
1500  PopLoop(cond);
1501  // Pop off iterator and array
1502  AddBCC(n->loc, AB_STACK, -2);
1503 }
std::string var
Definition: C4AulAST.h:307
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
C4ValueMapNames VarNamed
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::DoLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1541 of file C4AulCompiler.cpp.

References AB_COND.

1542 {
1543  int body = AddJumpTarget();
1544  PushLoop();
1545  if (SafeVisit(n->body))
1546  MaybePopValueOf(n->body);
1547  int cond = AddJumpTarget();
1548  SafeVisit(n->cond);
1549  AddJumpTo(n->loc, AB_COND, body);
1550  PopLoop(cond);
1551 }
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::WhileLoop n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1553 of file C4AulCompiler.cpp.

References AB_CONDN.

1554 {
1555  int cond = AddJumpTarget();
1556  PushLoop();
1557  SafeVisit(n->cond);
1558  active_loops.top().breaks.push_back(AddBCC(n->cond->loc, AB_CONDN));
1559  if (SafeVisit(n->body))
1560  MaybePopValueOf(n->body);
1561  // continue starts the next iteration of the loop
1562  AddLoopControl(n->loc, Loop::Control::Continue);
1563  PopLoop(cond);
1564 }
StmtPtr body
Definition: C4AulAST.h:291
ExprPtr cond
Definition: C4AulAST.h:290
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Break n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1566 of file C4AulCompiler.cpp.

References ENSURE_COND.

1567 {
1568  ENSURE_COND(!active_loops.empty(), "'break' outside loop");
1569  AddLoopControl(n->loc, Loop::Control::Break);
1570 }
#define ENSURE_COND(cond, failmsg)
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Continue n)
overridevirtual

Reimplemented from aul::AstVisitor.

Definition at line 1572 of file C4AulCompiler.cpp.

References ENSURE_COND.

1573 {
1574  ENSURE_COND(!active_loops.empty(), "'continue' outside loop");
1575  AddLoopControl(n->loc, Loop::Control::Continue);
1576 }
#define ENSURE_COND(cond, failmsg)
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::If n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1578 of file C4AulCompiler.cpp.

References AB_CONDN, and AB_JUMP.

1579 {
1580  SafeVisit(n->cond);
1581  int jump = AddBCC(n->loc, AB_CONDN);
1582  // Warn if we're controlling a no-op ("if (...);")
1583  if (dynamic_cast<::aul::ast::Noop*>(n->iftrue.get()))
1584  {
1585  Warn(target_host, host, n->iftrue->loc, Fn, C4AulWarningId::empty_if);
1586  }
1587  if (SafeVisit(n->iftrue))
1588  MaybePopValueOf(n->iftrue);
1589 
1590  if (dynamic_cast<::aul::ast::Noop*>(n->iffalse.get()))
1591  {
1592  Warn(target_host, host, n->iffalse->loc, Fn, C4AulWarningId::empty_if);
1593  }
1594 
1595  if (n->iffalse)
1596  {
1597  int jumpout = AddBCC(n->loc, AB_JUMP);
1598  UpdateJump(jump, AddJumpTarget());
1599  jump = jumpout;
1600  if (SafeVisit(n->iffalse))
1601  MaybePopValueOf(n->iffalse);
1602  }
1603  UpdateJump(jump, AddJumpTarget());
1604 }
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
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::VarDecl n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1606 of file C4AulCompiler.cpp.

References AB_POP_TO, AB_STACK, and Object().

1607 {
1608  for (const auto &dec : n->decls)
1609  {
1610  const char *cname = dec.name.c_str();
1611  switch (n->scope)
1612  {
1613  case ::aul::ast::VarDecl::Scope::Func:
1614  if (dec.init)
1615  {
1616  // Emit code for the initializer
1617  SafeVisit(dec.init);
1618  int var_idx = Fn->VarNamed.GetItemNr(cname);
1619  assert(var_idx >= 0 && "CodegenAstVisitor: var not found in variable table");
1620  if (var_idx < 0)
1621  {
1622  AddBCC(n->loc, AB_STACK, -1);
1623  throw Error(target_host, host, n, Fn, "internal error: var not found in variable table: %s", cname);
1624  }
1625  AddVarAccess(n->loc, AB_POP_TO, var_idx);
1626  }
1627  break;
1629  case ::aul::ast::VarDecl::Scope::Global:
1630  // Object-local and global constants are handled by ConstantResolver.
1631  break;
1632  }
1633  }
1634 }
C4ValueMapNames VarNamed
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459
std::vector< Var > decls
Definition: C4AulAST.h:365
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
const char * loc
Definition: C4AulAST.h:123

Here is the call graph for this function:

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1636 of file C4AulCompiler.cpp.

References C4ScriptHost::Engine, C4StringTable::FindString(), C4PropList::GetFunc(), C4AulFunc::GetName(), C4ScriptHost::GetPropList(), C4AulScriptEngine::GetPropList(), C4AulScriptFunc::OwnerOverloaded, C4AulFunc::Parent, C4AulScriptFunc::pOrgScript, C4AulFunc::SFunc(), and Strings.

1637 {
1638  assert(!Fn && "CodegenAstVisitor: function declaration encountered within active function");
1639  if (Fn)
1640  throw Error(target_host, host, n, Fn, "internal error: function declaration for '%s' encountered within active function", n->name.c_str());
1641 
1642  C4PropListStatic *Parent = n->is_global ? target_host->Engine->GetPropList() : target_host->GetPropList();
1643 
1644  C4String *name = ::Strings.FindString(n->name.c_str());
1645  C4AulFunc *f = Parent->GetFunc(name);
1646  while (f)
1647  {
1648  if (f->SFunc() && f->SFunc()->pOrgScript == host && f->Parent == Parent)
1649  {
1650  if (Fn)
1651  Warn(target_host, host, n, Fn, C4AulWarningId::redeclaration, "function", f->GetName());
1652  Fn = f->SFunc();
1653  }
1654  f = f->SFunc() ? f->SFunc()->OwnerOverloaded : nullptr;
1655  }
1656 
1657  if (!Fn && Parent->HasProperty(name))
1658  {
1659  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());
1660  }
1661 
1662  assert(Fn && "CodegenAstVisitor: unable to find function definition");
1663  if (!Fn)
1664  throw Error(target_host, host, n, Fn, "internal error: unable to find function definition for %s", n->name.c_str());
1665 
1666  // If this isn't a global function, but there is a global one with
1667  // the same name, and this function isn't overloading a different
1668  // one, add the global function to the overload chain
1669  if (!n->is_global && !Fn->OwnerOverloaded)
1670  {
1671  C4AulFunc *global_parent = target_host->Engine->GetFunc(Fn->GetName());
1672  if (global_parent)
1673  Fn->SetOverloaded(global_parent);
1674  }
1675 
1676  try
1677  {
1678  EmitFunctionCode(n);
1679  Fn = nullptr;
1680  }
1681  catch (...)
1682  {
1683  Fn = nullptr;
1684  throw;
1685  }
1686 }
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
C4String * FindString(const char *strString) const
const char * GetName() const
Definition: C4AulFunc.h:56
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:105
C4ScriptHost * pOrgScript
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:76
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:50
C4AulFunc * OwnerOverloaded
C4StringTable Strings
Definition: C4Globals.cpp:42
std::string name
Definition: C4AulAST.h:390
C4PropListStatic * Parent
Definition: C4AulFunc.h:55
virtual C4AulScriptFunc * SFunc()
Definition: C4AulFunc.h:65

Here is the call graph for this function:

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1688 of file C4AulCompiler.cpp.

References AB_NIL.

1689 {
1690  AddBCC(n->loc, AB_NIL);
1691  throw Error(target_host, host, n, Fn, "can't define a function in a function-scoped proplist");
1692 }
const char * loc
Definition: C4AulAST.h:123
void C4AulCompiler::CodegenAstVisitor::visit ( const ::aul::ast::Script n)
overridevirtual

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1694 of file C4AulCompiler.cpp.

1695 {
1696  for (const auto &d : n->declarations)
1697  {
1698  SafeVisit(d);
1699  }
1700 }
std::vector< DeclPtr > declarations
Definition: C4AulAST.h:425

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