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::Noop *)
 
template<class T >
void visit (const T *)=delete
 
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 182 of file C4AulCompiler.cpp.

Constructor & Destructor Documentation

◆ CodegenAstVisitor() [1/2]

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

Definition at line 328 of file C4AulCompiler.cpp.

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

◆ CodegenAstVisitor() [2/2]

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

Definition at line 329 of file C4AulCompiler.cpp.

329 : Fn(func), target_host(func->pOrgScript), host(target_host) {}
C4ScriptHost * pOrgScript

◆ ~CodegenAstVisitor()

C4AulCompiler::CodegenAstVisitor::~CodegenAstVisitor ( )
overridedefault

Member Function Documentation

◆ EmitFunctionCode()

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

Definition at line 365 of file C4AulCompiler.cpp.

366  {
367  // This dynamic_cast resolves the problem where we have a Function*
368  // and want to emit code to it. All classes derived from Function
369  // are also ultimately derived from Node, so this call is fine
370  // without any additional checking.
371  EmitFunctionCode(n, dynamic_cast<const ::aul::ast::Node*>(n));
372  }

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

Here is the caller graph for this function:

◆ visit() [1/34]

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

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 92 of file C4AulAST.h.

92 {}

◆ visit() [2/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1069 of file C4AulCompiler.cpp.

1070 {
1071  StackGuard g(this, 1);
1072  for (const auto &e : n->values)
1073  {
1074  SafeVisit(e);
1075  }
1076  AddBCC(n->loc, AB_NEW_ARRAY, n->values.size());
1077  type_of_stack_top = C4V_Array;
1078 }
@ AB_NEW_ARRAY
@ C4V_Array
Definition: C4Value.h:30
std::vector< ExprPtr > values
Definition: C4AulAST.h:180
const char * loc
Definition: C4AulAST.h:123

References AB_NEW_ARRAY, and C4V_Array.

◆ visit() [3/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1254 of file C4AulCompiler.cpp.

1255 {
1256  StackGuard g(this, 1);
1257  SafeVisit(n->lhs);
1258  try
1259  {
1260  C4AulBCC setter = MakeSetter(n->loc, false);
1261  SafeVisit(n->rhs);
1262  AddBCC(n->loc, setter);
1263  }
1264  catch (C4AulParseError &e)
1265  {
1266  HandleError(e);
1267  }
1268  // Assignment does not change the type of the variable
1269 }

◆ visit() [4/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1215 of file C4AulCompiler.cpp.

1216 {
1217  StackGuard g(this, 1);
1218 
1219  SafeVisit(n->lhs);
1220 
1221  const auto &op = C4ScriptOpMap[n->op];
1222  if (op.Code == AB_JUMPAND || op.Code == AB_JUMPOR || op.Code == AB_JUMPNNIL)
1223  {
1224  // Short-circuiting operators. These are slightly more complex
1225  // because we don't want to evaluate their rhs operand when the
1226  // lhs one already decided the result
1227  int jump = AddBCC(n->loc, op.Code);
1228  SafeVisit(n->rhs);
1229  UpdateJump(jump, AddJumpTarget());
1230  }
1231  else if (op.Changer)
1232  {
1233  try
1234  {
1235  C4AulBCC setter = MakeSetter(n->loc, true);
1236  SafeVisit(n->rhs);
1237  AddBCC(n->loc, op.Code);
1238  AddBCC(n->loc, setter);
1239  }
1240  catch (C4AulParseError &e)
1241  {
1242  HandleError(e);
1243  }
1244  }
1245  else
1246  {
1247  SafeVisit(n->rhs);
1248  AddBCC(n->loc, op.Code, 0);
1249  }
1250 
1251  type_of_stack_top = op.RetType;
1252 }
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:275
@ AB_JUMPAND
@ AB_JUMPNNIL
@ AB_JUMPOR

References AB_JUMPAND, AB_JUMPNNIL, AB_JUMPOR, and C4ScriptOpMap.

◆ visit() [5/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1478 of file C4AulCompiler.cpp.

1479 {
1480  auto scope = enterScope();
1481  for (const auto &s : n->children)
1482  {
1483  StackGuard g(this, 0);
1484  if (SafeVisit(s))
1485  {
1486  // If the statement has left a stack value, pop it off
1487  MaybePopValueOf(s);
1488  }
1489  }
1490 }
#define s
std::vector< StmtPtr > children
Definition: C4AulAST.h:273

References s.

◆ visit() [6/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1062 of file C4AulCompiler.cpp.

1063 {
1064  StackGuard g(this, 1);
1065  AddBCC(n->loc, AB_BOOL, n->value);
1066  type_of_stack_top = C4V_Bool;
1067 }
@ AB_BOOL
@ C4V_Bool
Definition: C4Value.h:27

References AB_BOOL, and C4V_Bool.

◆ visit() [7/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1671 of file C4AulCompiler.cpp.

1672 {
1673  ENSURE_COND(!active_loops.empty(), "'break' outside loop");
1674  AddLoopControl(n->loc, Loop::Control::Break);
1675 }
#define ENSURE_COND(cond, failmsg)

References ENSURE_COND.

◆ visit() [8/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1293 of file C4AulCompiler.cpp.

1294 {
1295  const char *cname = n->callee.c_str();
1296 
1297  if (n->callee == C4AUL_DebugBreak)
1298  {
1299  if (n->context)
1300  throw Error(target_host, host, n, Fn, R"("%s" can't be called in a different context)", cname);
1301  if (!n->args.empty())
1302  throw Error(target_host, host, n, Fn, R"("%s" must not have any arguments)", cname);
1303 
1304  AddBCC(n->loc, AB_DEBUG);
1305  // Add a pseudo-nil to keep the stack balanced
1306  AddBCC(n->loc, AB_NIL);
1307  type_of_stack_top = C4V_Nil;
1308  return;
1309  }
1310 
1311  if (n->callee == C4AUL_Inherited || n->callee == C4AUL_SafeInherited)
1312  {
1313  // inherited can only be called within the same context
1314  if (n->context)
1315  {
1316  throw Error(target_host, host, n, Fn, R"("%s" can't be called in a different context)", cname);
1317  }
1318  }
1319 
1320  if (n->callee == C4AUL_Inherited && !Fn->OwnerOverloaded)
1321  {
1322  throw Error(target_host, host, n, Fn, "inherited function not found (use " C4AUL_SafeInherited " to disable this message)");
1323  }
1324 
1325  const auto pre_call_stack = stack_height;
1326 
1327  if (n->context)
1328  SafeVisit(n->context);
1329 
1330  std::vector<C4V_Type> known_par_types;
1331  known_par_types.reserve(n->args.size());
1332 
1333  for (const auto &arg : n->args)
1334  {
1335  SafeVisit(arg);
1336  known_par_types.push_back(type_of_stack_top);
1337  }
1338 
1339  C4AulFunc *callee = nullptr;
1340 
1341  // Special handling for the overload chain
1342  if (n->callee == C4AUL_Inherited || n->callee == C4AUL_SafeInherited)
1343  {
1344  callee = Fn->OwnerOverloaded;
1345  }
1346 
1347  size_t fn_argc = C4AUL_MAX_Par;
1348  if (!n->context)
1349  {
1350  // if this is a function without explicit context, we resolve it
1351  if (!callee)
1352  callee = Fn->Parent->GetFunc(cname);
1353  if (!callee && target_host)
1354  callee = target_host->Engine->GetFunc(cname);
1355 
1356  if (callee)
1357  {
1358  fn_argc = callee->GetParCount();
1359  }
1360  else
1361  {
1362  // pop all args off the stack
1363  if (!n->args.empty())
1364  AddBCC(n->loc, AB_STACK, -(intptr_t)n->args.size());
1365  // and "return" nil
1366  AddBCC(n->loc, AB_NIL);
1367  type_of_stack_top = C4V_Nil;
1368 
1369  if (n->callee != C4AUL_SafeInherited)
1370  {
1371  HandleError(Error(target_host, host, n, Fn, "called function not found: %s", cname));
1372  }
1373  return;
1374  }
1375  }
1376 
1377  if (n->args.size() > fn_argc)
1378  {
1379  // Pop off any args that are over the limit
1380  Warn(target_host, host, n->args[fn_argc].get(), Fn, C4AulWarningId::arg_count_mismatch,
1381  cname, (unsigned)n->args.size(), fn_argc);
1382  AddBCC(n->loc, AB_STACK, fn_argc - n->args.size());
1383  }
1384  else if (n->args.size() < fn_argc)
1385  {
1386  if (n->append_unnamed_pars)
1387  {
1388  assert(Fn->GetParCount() == C4AUL_MAX_Par);
1389  int missing_par_count = fn_argc - n->args.size();
1390  int available_par_count = Fn->GetParCount() - Fn->ParNamed.iSize;
1391  for (int i = 0; i < std::min(missing_par_count, available_par_count); ++i)
1392  {
1393  AddVarAccess(n->loc, AB_DUP, -Fn->GetParCount() + Fn->ParNamed.iSize + i);
1394  }
1395  // Fill up remaining, unsettable parameters with nil
1396  if (available_par_count < missing_par_count)
1397  AddBCC(n->loc, AB_STACK, missing_par_count - available_par_count);
1398  }
1399  else if (fn_argc > n->args.size())
1400  {
1401  // Add nil for each missing parameter
1402  AddBCC(n->loc, AB_STACK, fn_argc - n->args.size());
1403  }
1404  }
1405 
1406  // Check passed parameters for this call (as far as possible)
1407  std::vector<C4V_Type> expected_par_types;
1408  if (n->context)
1409  {
1410  AddBCC(n->loc, n->safe_call ? AB_CALLFS : AB_CALL, (intptr_t)::Strings.RegString(cname));
1411  // Since we don't know the context in which this call will happen at
1412  // runtime, we'll check whether all available functions with the same
1413  // name agree on their parameters.
1414  const C4AulFunc *candidate = target_host ? target_host->Engine->GetFirstFunc(cname) : nullptr;
1415  if (candidate)
1416  {
1417  expected_par_types.assign(candidate->GetParType(), candidate->GetParType() + candidate->GetParCount());
1418  while ((candidate = target_host->Engine->GetNextSNFunc(candidate)) != nullptr)
1419  {
1420  if (candidate->GetParCount() > expected_par_types.size())
1421  {
1422  expected_par_types.resize(candidate->GetParCount(), C4V_Any);
1423  }
1424  for (size_t i = 0; i < expected_par_types.size(); ++i)
1425  {
1426  C4V_Type a = expected_par_types[i];
1427  C4V_Type b = candidate->GetParType()[i];
1428  // If we can convert one of the types into the other
1429  // without a warning, use the wider one
1430  bool implicit_a_to_b = !C4Value::WarnAboutConversion(a, b);
1431  bool implicit_b_to_a = !C4Value::WarnAboutConversion(b, a);
1432  if (implicit_a_to_b && !implicit_b_to_a)
1433  expected_par_types[i] = b;
1434  else if (implicit_b_to_a && !implicit_a_to_b)
1435  expected_par_types[i] = a;
1436  // but if we can convert neither of the types into the
1437  // other, give up and assume the user will do the right
1438  // thing
1439  else if (!implicit_a_to_b && !implicit_b_to_a)
1440  expected_par_types[i] = C4V_Any;
1441  }
1442  }
1443  }
1444  type_of_stack_top = C4V_Any;
1445  }
1446  else
1447  {
1448  assert(callee);
1449  AddBCC(n->loc, AB_FUNC, (intptr_t)callee);
1450  expected_par_types.assign(callee->GetParType(), callee->GetParType() + callee->GetParCount());
1451  type_of_stack_top = callee->GetRetType();
1452  }
1453 
1454  // Check parameters
1455  for (size_t i = 0; i < std::min(known_par_types.size(), expected_par_types.size()); ++i)
1456  {
1457  C4V_Type from = known_par_types[i];
1458  C4V_Type to = expected_par_types[i];
1459  if (C4Value::WarnAboutConversion(from, to))
1460  {
1461  Warn(target_host, host, n->args[i].get(), Fn, C4AulWarningId::arg_type_mismatch, (unsigned)i, cname, GetC4VName(from), GetC4VName(to));
1462  }
1463  }
1464 
1465  // We leave one value (the return value) on the stack
1466  assert(pre_call_stack + 1 == stack_height);
1467 }
#define C4AUL_SafeInherited
#define C4AUL_Inherited
#define C4AUL_DebugBreak
#define C4AUL_MAX_Par
Definition: C4AulFunc.h:26
@ AB_DEBUG
@ AB_CALLFS
@ AB_CALL
@ AB_FUNC
@ AB_NIL
@ AB_STACK
@ AB_DUP
C4StringTable Strings
Definition: C4Globals.cpp:42
#define a
#define b
const char * GetC4VName(const C4V_Type Type)
Definition: C4Value.cpp:32
C4V_Type
Definition: C4Value.h:24
@ C4V_Any
Definition: C4Value.h:37
@ C4V_Nil
Definition: C4Value.h:25
virtual C4V_Type GetRetType() const =0
C4PropListStatic * Parent
Definition: C4AulFunc.h:55
virtual const C4V_Type * GetParType() const =0
virtual int GetParCount() const
Definition: C4AulFunc.h:69
C4AulFunc * GetNextSNFunc(const C4AulFunc *After)
Definition: C4Aul.h:119
C4AulFunc * GetFirstFunc(const char *Name)
Definition: C4Aul.h:117
C4AulFunc * OwnerOverloaded
C4ValueMapNames ParNamed
int GetParCount() const override
C4AulFunc * GetFunc(C4PropertyName k) const
Definition: C4PropList.h:109
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:77
C4String * RegString(StdStrBuf String)
static bool WarnAboutConversion(C4V_Type Type, C4V_Type vtToType)
Definition: C4Value.cpp:111
bool append_unnamed_pars
Definition: C4AulAST.h:255
std::vector< ExprPtr > args
Definition: C4AulAST.h:257
std::string callee
Definition: C4AulAST.h:258

References C4AUL_DebugBreak.

◆ visit() [9/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1677 of file C4AulCompiler.cpp.

1678 {
1679  ENSURE_COND(!active_loops.empty(), "'continue' outside loop");
1680  AddLoopControl(n->loc, Loop::Control::Continue);
1681 }

References ENSURE_COND.

◆ visit() [10/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1636 of file C4AulCompiler.cpp.

1637 {
1638  auto scope = enterScope();
1639  int body = AddJumpTarget();
1640  PushLoop();
1641  if (SafeVisit(n->body))
1642  MaybePopValueOf(n->body);
1643  int cond = AddJumpTarget();
1644  // XXX:
1645  // Assignments in the condition here should warn as well (like they do in
1646  // if conditions) but a ton of code uses those assignments at the moment
1647  // and people are divided about allowing it
1648  SafeVisit(n->cond);
1649  AddJumpTo(n->loc, AB_COND, body);
1650  PopLoop(cond);
1651 }
@ AB_COND
ExprPtr cond
Definition: C4AulAST.h:290
StmtPtr body
Definition: C4AulAST.h:291

References AB_COND.

◆ visit() [11/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1501 of file C4AulCompiler.cpp.

1502 {
1503  // Bytecode arranged like this:
1504  // initializer
1505  // cond: condition
1506  // CONDN exit
1507  // body: body
1508  // incr: incrementor
1509  // JUMP cond
1510  // exit:
1511  //
1512  // continue jumps to incr
1513  // break jumps to exit
1514 
1515  auto scope = enterScope();
1516  if (n->init)
1517  {
1518  if (SafeVisit(n->init))
1519  MaybePopValueOf(n->init);
1520  }
1521  int cond = -1;
1522  PushLoop();
1523  if (n->cond)
1524  {
1525  // XXX:
1526  // Assignments in the condition here should warn as well (like they do in
1527  // if conditions) but a ton of code uses those assignments at the moment
1528  // and people are divided about allowing it
1529  cond = AddJumpTarget();
1530  SafeVisit(n->cond);
1531  active_loops.top().breaks.push_back(AddBCC(n->cond->loc, AB_CONDN));
1532  }
1533 
1534  int body = AddJumpTarget();
1535  if (!n->cond)
1536  cond = body;
1537  if (SafeVisit(n->body))
1538  MaybePopValueOf(n->body);
1539 
1540  int incr = -1;
1541  if (n->incr)
1542  {
1543  incr = AddJumpTarget();
1544  if (SafeVisit(n->incr))
1545  MaybePopValueOf(n->incr);
1546  }
1547  else
1548  {
1549  // If no incrementor exists, just jump straight to the condition
1550  incr = cond;
1551  }
1552  // start the next iteration of the loop
1553  AddJumpTo(n->loc, AB_JUMP, cond);
1554  PopLoop(incr);
1555 }
@ AB_CONDN
@ AB_JUMP

References AB_CONDN, and AB_JUMP.

◆ visit() [12/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1744 of file C4AulCompiler.cpp.

1745 {
1746  assert(!Fn && "CodegenAstVisitor: function declaration encountered within active function");
1747  if (Fn)
1748  throw Error(target_host, host, n, Fn, "internal error: function declaration for '%s' encountered within active function", n->name.c_str());
1749 
1750  C4PropListStatic *Parent = n->is_global ? target_host->Engine->GetPropList() : target_host->GetPropList();
1751 
1752  C4String *name = ::Strings.FindString(n->name.c_str());
1753  C4AulFunc *f = Parent->GetFunc(name);
1754  while (f)
1755  {
1756  if (f->SFunc() && f->SFunc()->pOrgScript == host && f->Parent == Parent)
1757  {
1758  if (Fn)
1759  Warn(target_host, host, n, Fn, C4AulWarningId::redeclaration, "function", f->GetName());
1760  Fn = f->SFunc();
1761  }
1762  f = f->SFunc() ? f->SFunc()->OwnerOverloaded : nullptr;
1763  }
1764 
1765  if (!Fn && Parent->HasProperty(name))
1766  {
1767  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());
1768  }
1769 
1770  assert(Fn && "CodegenAstVisitor: unable to find function definition");
1771  if (!Fn)
1772  throw Error(target_host, host, n, Fn, "internal error: unable to find function definition for %s", n->name.c_str());
1773 
1774  // If this isn't a global function, but there is a global one with
1775  // the same name, and this function isn't overloading a different
1776  // one, add the global function to the overload chain
1777  if (!n->is_global && !Fn->OwnerOverloaded)
1778  {
1779  C4AulFunc *global_parent = target_host->Engine->GetFunc(Fn->GetName());
1780  if (global_parent)
1781  Fn->SetOverloaded(global_parent);
1782  }
1783 
1784  try
1785  {
1786  EmitFunctionCode(n);
1787  Fn = nullptr;
1788  }
1789  catch (...)
1790  {
1791  Fn = nullptr;
1792  throw;
1793  }
1794 }
const char * GetName() const
Definition: C4AulFunc.h:56
virtual C4AulScriptFunc * SFunc()
Definition: C4AulFunc.h:65
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
void SetOverloaded(C4AulFunc *)
bool HasProperty(C4String *k) const
Definition: C4PropList.h:122
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:51
C4String * FindString(const char *strString) const
std::string name
Definition: C4AulAST.h:390

◆ visit() [13/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1796 of file C4AulCompiler.cpp.

1797 {
1798  AddBCC(n->loc, AB_NIL);
1799  throw Error(target_host, host, n, Fn, "can't define a function in a function-scoped proplist");
1800 }

References AB_NIL.

◆ visit() [14/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1683 of file C4AulCompiler.cpp.

1684 {
1685  auto scope = enterScope();
1686  WarnOnAssignment(n->cond);
1687  SafeVisit(n->cond);
1688  int jump = AddBCC(n->loc, AB_CONDN);
1689  // Warn if we're controlling a no-op ("if (...);")
1690  if (dynamic_cast<::aul::ast::Noop*>(n->iftrue.get()))
1691  {
1692  Warn(target_host, host, n->iftrue->loc, Fn, C4AulWarningId::empty_if);
1693  }
1694  if (SafeVisit(n->iftrue))
1695  MaybePopValueOf(n->iftrue);
1696 
1697  if (dynamic_cast<::aul::ast::Noop*>(n->iffalse.get()))
1698  {
1699  Warn(target_host, host, n->iffalse->loc, Fn, C4AulWarningId::empty_if);
1700  }
1701 
1702  if (n->iffalse)
1703  {
1704  int jumpout = AddBCC(n->loc, AB_JUMP);
1705  UpdateJump(jump, AddJumpTarget());
1706  jump = jumpout;
1707  if (SafeVisit(n->iffalse))
1708  MaybePopValueOf(n->iffalse);
1709  }
1710  UpdateJump(jump, AddJumpTarget());
1711 }
ExprPtr cond
Definition: C4AulAST.h:338
StmtPtr iftrue
Definition: C4AulAST.h:339
StmtPtr iffalse
Definition: C4AulAST.h:339

References AB_CONDN.

◆ visit() [15/34]

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

Reimplemented in C4AulCompiler::PreparseAstVisitor.

Definition at line 91 of file C4AulAST.h.

91 {}

◆ visit() [16/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1055 of file C4AulCompiler.cpp.

1056 {
1057  StackGuard g(this, 1);
1058  AddBCC(n->loc, AB_INT, n->value);
1059  type_of_stack_top = C4V_Int;
1060 }
@ AB_INT
@ C4V_Int
Definition: C4Value.h:26
uint32_t value
Definition: C4AulAST.h:165

References AB_INT, and C4V_Int.

◆ visit() [17/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1093 of file C4AulCompiler.cpp.

1094 {
1095  StackGuard g(this, 1);
1096  AddBCC(n->loc, AB_NIL);
1097  type_of_stack_top = C4V_Nil;
1098 }

References AB_NIL, and C4V_Nil.

◆ visit() [18/34]

virtual void aul::AstVisitor::visit
inlineinherited

Definition at line 63 of file C4AulAST.h.

63 {}

◆ visit() [19/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1046 of file C4AulCompiler.cpp.

1046 {}

Referenced by C4AulCompiler::Compile().

Here is the caller graph for this function:

◆ visit() [20/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1469 of file C4AulCompiler.cpp.

1470 {
1471  StackGuard g(this, 1);
1472 
1473  SafeVisit(n->arg);
1474  AddBCC(n->loc, AB_PAR);
1475  type_of_stack_top = C4V_Any;
1476 }
@ AB_PAR

References AB_PAR, and C4V_Any.

◆ visit() [21/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1080 of file C4AulCompiler.cpp.

1081 {
1082  StackGuard g(this, 1);
1083  for (const auto &e : n->values)
1084  {
1085  StackGuard g(this, 2);
1086  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(e.first.c_str()));
1087  SafeVisit(e.second);
1088  }
1089  AddBCC(n->loc, AB_NEW_PROPLIST, n->values.size());
1090  type_of_stack_top = C4V_PropList;
1091 }
@ AB_STRING
@ AB_NEW_PROPLIST
@ C4V_PropList
Definition: C4Value.h:28
std::vector< std::pair< std::string, ExprPtr > > values
Definition: C4AulAST.h:187

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

Here is the call graph for this function:

◆ visit() [22/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1557 of file C4AulCompiler.cpp.

1558 {
1559  // Bytecode arranged like this:
1560  // condition (aka iterated array)
1561  // INT 0 (the loop index variable)
1562  // cond: FOREACH_NEXT
1563  // JUMP exit
1564  // body: body
1565  // JUMP cond
1566  // exit: STACK -2 (to clean the iteration variables)
1567  //
1568  // continue jumps to cond
1569  // break jumps to exit
1570 
1571  auto scope = enterScope();
1572  scopes.front().variables.insert(n->var);
1573 
1574  const char *cname = n->var.c_str();
1575  int var_id = Fn->VarNamed.GetItemNr(cname);
1576  assert(var_id != -1 && "CodegenAstVisitor: unable to find variable in foreach");
1577  if (var_id == -1)
1578  throw Error(target_host, host, n, Fn, "internal error: unable to find variable in foreach: %s", cname);
1579  // Emit code for array
1580  SafeVisit(n->cond);
1581  // Emit code for iteration
1582  AddBCC(n->loc, AB_INT, 0);
1583  int cond = AddJumpTarget();
1584  PushLoop();
1585  AddVarAccess(n->loc, AB_FOREACH_NEXT, var_id);
1586  AddLoopControl(n->loc, Loop::Control::Break); // Will be skipped by AB_FOREACH_NEXT as long as more entries exist
1587 
1588  // Emit body
1589  if (SafeVisit(n->body))
1590  MaybePopValueOf(n->body);
1591  // continue starts the next iteration of the loop
1592  AddLoopControl(n->loc, Loop::Control::Continue);
1593  PopLoop(cond);
1594  // Pop off iterator and array
1595  AddBCC(n->loc, AB_STACK, -2);
1596 }
@ AB_FOREACH_NEXT
C4ValueMapNames VarNamed
int32_t GetItemNr(const char *strName) const
Definition: C4ValueMap.cpp:459
std::string var
Definition: C4AulAST.h:307

◆ visit() [23/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1492 of file C4AulCompiler.cpp.

1493 {
1494  StackGuard g(this, 0);
1495 
1496  WarnOnAssignment(n->value);
1497  SafeVisit(n->value);
1498  AddBCC(n->loc, AB_RETURN);
1499 }
@ AB_RETURN
ExprPtr value
Definition: C4AulAST.h:284

References AB_RETURN.

◆ visit() [24/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1802 of file C4AulCompiler.cpp.

1803 {
1804  for (const auto &d : n->declarations)
1805  {
1806  SafeVisit(d);
1807  }
1808 }
std::vector< DeclPtr > declarations
Definition: C4AulAST.h:425

◆ visit() [25/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1282 of file C4AulCompiler.cpp.

1283 {
1284  StackGuard g(this, 1);
1285  SafeVisit(n->object);
1286  SafeVisit(n->start);
1287  SafeVisit(n->end);
1288  AddBCC(n->loc, AB_ARRAY_SLICE);
1289 
1290  type_of_stack_top = C4V_Array;
1291 }
@ AB_ARRAY_SLICE

References AB_ARRAY_SLICE, and C4V_Array.

◆ visit() [26/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1048 of file C4AulCompiler.cpp.

1049 {
1050  StackGuard g(this, 1);
1051  AddBCC(n->loc, AB_STRING, (intptr_t)::Strings.RegString(n->value.c_str()));
1052  type_of_stack_top = C4V_String;
1053 }
@ C4V_String
Definition: C4Value.h:29
std::string value
Definition: C4AulAST.h:157

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

Here is the call graph for this function:

◆ visit() [27/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1271 of file C4AulCompiler.cpp.

1272 {
1273  StackGuard g(this, 1);
1274  SafeVisit(n->object);
1275  SafeVisit(n->index);
1276  AddBCC(n->loc, AB_ARRAYA);
1277 
1278  // FIXME: Check if the subscripted object is a literal and if so, retrieve type
1279  type_of_stack_top = C4V_Any;
1280 }
@ AB_ARRAYA

References AB_ARRAYA, and C4V_Any.

◆ visit() [28/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1100 of file C4AulCompiler.cpp.

1101 {
1102  StackGuard g(this, 1);
1103  AddBCC(n->loc, AB_THIS);
1104  type_of_stack_top = C4V_PropList;
1105 }
@ AB_THIS

References AB_THIS, and C4V_PropList.

◆ visit() [29/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1191 of file C4AulCompiler.cpp.

1192 {
1193  StackGuard g(this, 1);
1194 
1195  n->operand->accept(this);
1196  const auto &op = C4ScriptOpMap[n->op];
1197  if (op.Changer)
1198  {
1199  C4AulBCC setter = MakeSetter(n->loc, true);
1200  AddBCC(n->loc, op.Code, 0);
1201  AddBCC(n->loc, setter);
1202  // On postfix inc/dec, regenerate the previous value
1203  if (op.Postfix && (op.Code == AB_Inc || op.Code == AB_Dec))
1204  {
1205  AddBCC(n->loc, op.Code == AB_Inc ? AB_Dec : AB_Inc, 1);
1206  }
1207  }
1208  else
1209  {
1210  AddBCC(n->loc, op.Code);
1211  }
1212  type_of_stack_top = op.RetType;
1213 }
@ AB_Inc
@ AB_Dec

References AB_Dec, AB_Inc, and C4ScriptOpMap.

◆ visit() [30/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1713 of file C4AulCompiler.cpp.

1714 {
1715  for (const auto &dec : n->decls)
1716  {
1717  const char *cname = dec.name.c_str();
1718  switch (n->scope)
1719  {
1720  case ::aul::ast::VarDecl::Scope::Func:
1721  scopes.front().variables.insert(dec.name);
1722  if (dec.init)
1723  {
1724  // Emit code for the initializer
1725  SafeVisit(dec.init);
1726  int var_idx = Fn->VarNamed.GetItemNr(cname);
1727  assert(var_idx >= 0 && "CodegenAstVisitor: var not found in variable table");
1728  if (var_idx < 0)
1729  {
1730  AddBCC(n->loc, AB_STACK, -1);
1731  throw Error(target_host, host, n, Fn, "internal error: var not found in variable table: %s", cname);
1732  }
1733  AddVarAccess(n->loc, AB_POP_TO, var_idx);
1734  }
1735  break;
1737  case ::aul::ast::VarDecl::Scope::Global:
1738  // Object-local and global constants are handled by ConstantResolver.
1739  break;
1740  }
1741  }
1742 }
C4Object * Object(C4PropList *_this)
Definition: C4AulDefFunc.h:34
@ AB_POP_TO
std::vector< Var > decls
Definition: C4AulAST.h:365

References AB_STACK.

◆ visit() [31/34]

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

Reimplemented from aul::AstVisitor.

Definition at line 1107 of file C4AulCompiler.cpp.

1108 {
1109  StackGuard g(this, 1);
1110  assert(Fn);
1111  assert(!scopes.empty());
1112  C4Value dummy;
1113  const char *cname = n->identifier.c_str();
1114  C4String *interned = ::Strings.FindString(cname);
1115 
1116  // Reset known type of top of value stack so we don't keep the old one around
1117  type_of_stack_top = C4V_Any;
1118 
1119  // Lookup order: Parameters > var > local > global > global const
1120  // Why parameters are considered before function-scoped variables
1121  // you ask? I've no idea, but that's how it was before I started
1122  // changing things.
1123  // NOTE: If you change this, remember to also change the warning
1124  // (variable_shadows_variable) in PreparseAstVisitor.
1125  if (Fn->ParNamed.GetItemNr(cname) != -1)
1126  {
1127  int pos = Fn->ParNamed.GetItemNr(cname);
1128  AddVarAccess(n->loc, AB_DUP, -Fn->GetParCount() + pos);
1129  type_of_stack_top = Fn->GetParType()[pos];
1130  }
1131  else if (Fn->VarNamed.GetItemNr(cname) != -1)
1132  {
1133  const bool in_scope = end(scopes) != std::find_if(begin(scopes), end(scopes), [n](const Scope &scope) {
1134  return scope.variables.find(n->identifier) != scope.variables.end();
1135  });
1136  if (!in_scope)
1137  {
1138  Warn(target_host, host, n, Fn, C4AulWarningId::variable_out_of_scope, cname);
1139  }
1140  AddVarAccess(n->loc, AB_DUP, Fn->VarNamed.GetItemNr(cname));
1141  }
1142  // Can't use Fn->Parent->HasProperty here because that only returns true
1143  // for immediate properties, while we also want to interrogate prototypes
1144  else if (Fn->Parent && interned && Fn->Parent->GetPropertyByS(interned, &dummy))
1145  {
1146  AddBCC(n->loc, AB_LOCALN, (intptr_t)interned);
1147  }
1148  else if (ScriptEngine.GlobalNamedNames.GetItemNr(cname) != -1)
1149  {
1151  }
1152  else if (ScriptEngine.GlobalConstNames.GetItemNr(cname) != -1)
1153  {
1154  C4Value v;
1155  ENSURE_COND(ScriptEngine.GetGlobalConstant(cname, &v), "internal error: global constant not retrievable");
1156  switch (v.GetType())
1157  {
1158  case C4V_Nil:
1159  AddBCC(n->loc, AB_NIL);
1160  break;
1161  case C4V_Int:
1162  AddBCC(n->loc, AB_INT, v._getInt());
1163  break;
1164  case C4V_Bool:
1165  AddBCC(n->loc, AB_BOOL, v._getBool());
1166  break;
1167  case C4V_PropList:
1168  AddBCC(n->loc, AB_CPROPLIST, reinterpret_cast<intptr_t>(v._getPropList()));
1169  break;
1170  case C4V_String:
1171  AddBCC(n->loc, AB_STRING, reinterpret_cast<intptr_t>(v._getStr()));
1172  break;
1173  case C4V_Array:
1174  AddBCC(n->loc, AB_CARRAY, reinterpret_cast<intptr_t>(v._getArray()));
1175  break;
1176  case C4V_Function:
1177  AddBCC(n->loc, AB_CFUNCTION, reinterpret_cast<intptr_t>(v._getFunction()));
1178  default:
1179  AddBCC(n->loc, AB_NIL);
1180  throw Error(target_host, host, n, Fn, "internal error: global constant of unexpected type: %s (of type %s)", cname, v.GetTypeName());
1181  }
1182  type_of_stack_top = v.GetType();
1183  }
1184  else
1185  {
1186  AddBCC(n->loc, AB_NIL);
1187  throw Error(target_host, host, n, Fn, "symbol not found in any symbol table: %s", cname);
1188  }
1189 }
@ AB_CPROPLIST
@ AB_GLOBALN
@ AB_CARRAY
@ AB_LOCALN
@ AB_CFUNCTION
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
@ C4V_Function
Definition: C4Value.h:31
bool GetGlobalConstant(const char *szName, C4Value *pTargetValue)
Definition: C4Aul.cpp:133
C4ValueMapNames GlobalConstNames
Definition: C4Aul.h:141
C4ValueMapNames GlobalNamedNames
Definition: C4Aul.h:134
const C4V_Type * GetParType() const override
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:726
C4PropList * _getPropList() const
Definition: C4Value.h:129
bool _getBool() const
Definition: C4Value.h:123
C4V_Type GetType() const
Definition: C4Value.h:161
C4AulFunc * _getFunction() const
Definition: C4Value.h:128
int32_t _getInt() const
Definition: C4Value.h:122
C4ValueArray * _getArray() const
Definition: C4Value.h:127
C4String * _getStr() const
Definition: C4Value.h:126
const char * GetTypeName() const
Definition: C4Value.h:164
std::string identifier
Definition: C4AulAST.h:205

References AB_DUP, C4V_Any, C4StringTable::FindString(), and Strings.

Here is the call graph for this function:

◆ visit() [32/34]

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

Reimplemented from aul::DefaultRecursiveVisitor.

Definition at line 1653 of file C4AulCompiler.cpp.

1654 {
1655  auto scope = enterScope();
1656  int cond = AddJumpTarget();
1657  PushLoop();
1658  // XXX:
1659  // Assignments in the condition here should warn as well (like they do in
1660  // if conditions) but a ton of code uses those assignments at the moment
1661  // and people are divided about allowing it
1662  SafeVisit(n->cond);
1663  active_loops.top().breaks.push_back(AddBCC(n->cond->loc, AB_CONDN));
1664  if (SafeVisit(n->body))
1665  MaybePopValueOf(n->body);
1666  // continue starts the next iteration of the loop
1667  AddLoopControl(n->loc, Loop::Control::Continue);
1668  PopLoop(cond);
1669 }

References AB_CONDN.

◆ visit() [33/34]

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

◆ visit() [34/34]

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

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