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)
 
virtual ~CodegenAstVisitor ()
 
virtual void visit (const ::aul::ast::Noop *) override
 
virtual void visit (const ::aul::ast::StringLit *n) override
 
virtual void visit (const ::aul::ast::IntLit *n) override
 
virtual void visit (const ::aul::ast::BoolLit *n) override
 
virtual void visit (const ::aul::ast::ArrayLit *n) override
 
virtual void visit (const ::aul::ast::ProplistLit *n) override
 
virtual void visit (const ::aul::ast::NilLit *n) override
 
virtual void visit (const ::aul::ast::ThisLit *n) override
 
virtual void visit (const ::aul::ast::VarExpr *n) override
 
virtual void visit (const ::aul::ast::UnOpExpr *n) override
 
virtual void visit (const ::aul::ast::BinOpExpr *n) override
 
virtual void visit (const ::aul::ast::AssignmentExpr *n) override
 
virtual void visit (const ::aul::ast::SubscriptExpr *n) override
 
virtual void visit (const ::aul::ast::SliceExpr *n) override
 
virtual void visit (const ::aul::ast::CallExpr *n) override
 
virtual void visit (const ::aul::ast::ParExpr *n) override
 
virtual void visit (const ::aul::ast::Block *n) override
 
virtual void visit (const ::aul::ast::Return *n) override
 
virtual void visit (const ::aul::ast::ForLoop *n) override
 
virtual void visit (const ::aul::ast::RangeLoop *n) override
 
virtual void visit (const ::aul::ast::DoLoop *n) override
 
virtual void visit (const ::aul::ast::WhileLoop *n) override
 
virtual void visit (const ::aul::ast::Break *n) override
 
virtual void visit (const ::aul::ast::Continue *n) override
 
virtual void visit (const ::aul::ast::If *n) override
 
virtual void visit (const ::aul::ast::VarDecl *n) override
 
virtual void visit (const ::aul::ast::FunctionDecl *n) override
 
virtual void visit (const ::aul::ast::FunctionExpr *n) override
 
virtual 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 145 of file C4AulCompiler.cpp.

Constructor & Destructor Documentation

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

Definition at line 254 of file C4AulCompiler.cpp.

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

Definition at line 255 of file C4AulCompiler.cpp.

255 : Fn(func), target_host(func->pOrgScript), host(target_host) {}
C4ScriptHost * pOrgScript
virtual C4AulCompiler::CodegenAstVisitor::~CodegenAstVisitor ( )
inlinevirtual

Definition at line 257 of file C4AulCompiler.cpp.

257 {}

Member Function Documentation

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

Definition at line 291 of file C4AulCompiler.cpp.

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

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

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 96 of file C4AulAST.h.

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

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 97 of file C4AulAST.h.

97 {}
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 970 of file C4AulCompiler.cpp.

Referenced by C4AulCompiler::Compile().

970 {}

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 972 of file C4AulCompiler.cpp.

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

973 {
974  StackGuard g(this, 1);
975  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(n->value.c_str()));
976  type_of_stack_top = C4V_String;
977 }
C4String * RegString(StdStrBuf String)
C4StringTable Strings
Definition: C4Globals.cpp:42
std::string value
Definition: C4AulAST.h:162
const char * loc
Definition: C4AulAST.h:128

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 979 of file C4AulCompiler.cpp.

References AB_INT, and C4V_Int.

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

Reimplemented from aul::AstVisitor.

Definition at line 986 of file C4AulCompiler.cpp.

References AB_BOOL, and C4V_Bool.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 993 of file C4AulCompiler.cpp.

References AB_NEW_ARRAY, and C4V_Array.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1004 of file C4AulCompiler.cpp.

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

1005 {
1006  StackGuard g(this, 1);
1007  for (const auto &e : n->values)
1008  {
1009  StackGuard g(this, 2);
1010  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(e.first.c_str()));
1011  SafeVisit(e.second);
1012  }
1013  AddBCC(n->loc, AB_NEW_PROPLIST, n->values.size());
1014  type_of_stack_top = C4V_PropList;
1015 }
C4String * RegString(StdStrBuf String)
C4StringTable Strings
Definition: C4Globals.cpp:42
const char * loc
Definition: C4AulAST.h:128
std::vector< std::pair< std::string, ExprPtr > > values
Definition: C4AulAST.h:192

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 1017 of file C4AulCompiler.cpp.

References AB_NIL, and C4V_Nil.

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

Reimplemented from aul::AstVisitor.

Definition at line 1024 of file C4AulCompiler.cpp.

References AB_THIS, and C4V_PropList.

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

Reimplemented from aul::AstVisitor.

Definition at line 1031 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.

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

References AB_Dec, AB_Inc, and C4ScriptOpMap.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1131 of file C4AulCompiler.cpp.

References AB_JUMPAND, AB_JUMPNNIL, AB_JUMPOR, and C4ScriptOpMap.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1170 of file C4AulCompiler.cpp.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1187 of file C4AulCompiler.cpp.

References AB_ARRAYA, and C4V_Any.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1198 of file C4AulCompiler.cpp.

References AB_ARRAY_SLICE, and C4V_Array.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1209 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().

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

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 1385 of file C4AulCompiler.cpp.

References AB_PAR, and C4V_Any.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1394 of file C4AulCompiler.cpp.

References s.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1407 of file C4AulCompiler.cpp.

References AB_RETURN.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1415 of file C4AulCompiler.cpp.

References AB_CONDN, and AB_JUMP.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1466 of file C4AulCompiler.cpp.

References AB_FOREACH_NEXT, AB_INT, and AB_STACK.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1540 of file C4AulCompiler.cpp.

References AB_COND.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1552 of file C4AulCompiler.cpp.

References AB_CONDN.

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

Reimplemented from aul::AstVisitor.

Definition at line 1565 of file C4AulCompiler.cpp.

References ENSURE_COND.

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

Reimplemented from aul::AstVisitor.

Definition at line 1571 of file C4AulCompiler.cpp.

References ENSURE_COND.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1577 of file C4AulCompiler.cpp.

References AB_CONDN, and AB_JUMP.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1605 of file C4AulCompiler.cpp.

References AB_POP_TO, AB_STACK, and Object().

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

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 1635 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.

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

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 1687 of file C4AulCompiler.cpp.

References AB_NIL.

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1693 of file C4AulCompiler.cpp.

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

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