[Avida-SVN] r2402 - development/source/script
brysonda at myxo.css.msu.edu
brysonda at myxo.css.msu.edu
Fri Feb 29 13:54:46 PST 2008
Author: brysonda
Date: 2008-02-29 16:54:46 -0500 (Fri, 29 Feb 2008)
New Revision: 2402
Modified:
development/source/script/ASTree.cc
development/source/script/ASTree.h
development/source/script/AvidaScript.h
development/source/script/cDumpASTVisitor.cc
development/source/script/cSemanticASTVisitor.cc
development/source/script/cSemanticASTVisitor.h
development/source/script/cSymbolTable.h
Log:
AS: function definition semantics.
Modified: development/source/script/ASTree.cc
===================================================================
--- development/source/script/ASTree.cc 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/ASTree.cc 2008-02-29 21:54:46 UTC (rev 2402)
@@ -59,3 +59,9 @@
tListIterator<cASTNode> it(m_nodes);
while ((node = it.Next())) delete node;
}
+
+cASTFunctionDefinition::~cASTFunctionDefinition()
+{
+ delete m_args;
+ delete m_code;
+}
\ No newline at end of file
Modified: development/source/script/ASTree.h
===================================================================
--- development/source/script/ASTree.h 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/ASTree.h 2008-02-29 21:54:46 UTC (rev 2402)
@@ -306,16 +306,16 @@
public:
cASTFunctionDefinition(const cASFilePosition& fp, ASType_t type, const cString& name, cASTVariableDefinitionList* args)
: cASTNode(fp), m_type(type), m_name(name), m_args(args), m_code(NULL) { ; }
+ ~cASTFunctionDefinition();
- inline ASType_t GetType() { return m_type; }
+ inline ASType_t GetType() const { return m_type; }
inline const cString& GetName() { return m_name; }
inline cASTVariableDefinitionList* GetArguments() { return m_args; }
+ inline void ClearArguments() { m_args = NULL; }
inline void SetCode(cASTNode* code) { m_code = code; }
inline cASTNode* GetCode() { return m_code; }
- inline bool IsDefinition() { return (m_code); }
-
void Accept(cASTVisitor& visitor);
};
@@ -334,7 +334,7 @@
: cASTNode(fp), m_type(type), m_name(name), m_assign(NULL), m_dims(NULL), m_id(-1) { ; }
~cASTVariableDefinition() { delete m_assign; delete m_dims; }
- inline ASType_t GetType() { return m_type; }
+ inline ASType_t GetType() const { return m_type; }
inline const cString& GetName() { return m_name; }
inline void SetAssignmentExpression(cASTNode* assign) { delete m_assign; m_assign = assign; }
inline cASTNode* GetAssignmentExpression() { return m_assign; }
Modified: development/source/script/AvidaScript.h
===================================================================
--- development/source/script/AvidaScript.h 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/AvidaScript.h 2008-02-29 21:54:46 UTC (rev 2402)
@@ -117,6 +117,10 @@
AS_SEMANTIC_WARN__LAST,
AS_SEMANTIC_ERR_CANNOT_CAST,
+ AS_SEMANTIC_ERR_FUNCTION_DEFAULT_REQUIRED,
+ AS_SEMANTIC_ERR_FUNCTION_REDEFINITION,
+ AS_SEMANTIC_ERR_FUNCTION_RTYPE_MISMATCH,
+ AS_SEMANTIC_ERR_FUNCTION_SIGNATURE_MISMATCH,
AS_SEMANTIC_ERR_TOO_MANY_ARGUMENTS,
AS_SEMANTIC_ERR_UNDEFINED_TYPE_OP,
AS_SEMANTIC_ERR_UNPACK_WILD_NONARRAY,
Modified: development/source/script/cDumpASTVisitor.cc
===================================================================
--- development/source/script/cDumpASTVisitor.cc 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/cDumpASTVisitor.cc 2008-02-29 21:54:46 UTC (rev 2402)
@@ -193,7 +193,7 @@
void cDumpASTVisitor::visitFunctionDefinition(cASTFunctionDefinition& node)
{
indent();
- cout << (node.IsDefinition() ? "":"@") << "function: " << mapType(node.GetType()) << " " << node.GetName() << "(";
+ cout << (node.GetCode() ? "":"@") << "function: " << mapType(node.GetType()) << " " << node.GetName() << "(";
if (node.GetArguments()->GetSize()) {
cout << endl;
node.GetArguments()->Accept(*this);
@@ -204,7 +204,7 @@
indent();
cout << "{" << endl;
- if (node.IsDefinition()) {
+ if (node.GetCode()) {
m_depth++;
node.GetCode()->Accept(*this);
m_depth--;
Modified: development/source/script/cSemanticASTVisitor.cc
===================================================================
--- development/source/script/cSemanticASTVisitor.cc 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/cSemanticASTVisitor.cc 2008-02-29 21:54:46 UTC (rev 2402)
@@ -32,8 +32,8 @@
using namespace AvidaScript;
-#define SEMANTIC_ERROR(code, ...) reportError(true, AS_SEMANTIC_ERR_ ## code, node.GetFilePosition(), __LINE__, ##__VA_ARGS__)
-#define SEMANTIC_WARNING(code, ...) reportError(false, AS_SEMANTIC_WARN_ ## code, node.GetFilePosition(), __LINE__, ##__VA_ARGS__)
+#define SEMANTIC_ERROR(code, ...) reportError(AS_SEMANTIC_ERR_ ## code, node.GetFilePosition(), __LINE__, ##__VA_ARGS__)
+#define SEMANTIC_WARNING(code, ...) reportError(AS_SEMANTIC_WARN_ ## code, node.GetFilePosition(), __LINE__, ##__VA_ARGS__)
#define TOKEN(x) AS_TOKEN_ ## x
#define TYPE(x) AS_TYPE_ ## x
@@ -168,7 +168,87 @@
void cSemanticASTVisitor::visitFunctionDefinition(cASTFunctionDefinition& node)
{
- // @TODO - function definition
+ int fun_id = -1;
+ bool added = m_cur_symtbl->AddFunction(node.GetName(), node.GetType(), fun_id);
+
+ m_fun_stack.Push(sFunctionEntry(m_parent_scope, m_fun_id));
+ m_parent_scope = m_cur_symtbl;
+ m_fun_id = fun_id;
+
+ if (added) {
+ // Create new symtbl and scope
+ m_cur_symtbl = new cSymbolTable;
+ m_parent_scope->SetFunctionSymbolTable(fun_id, m_cur_symtbl);
+
+ // Check call signature
+ cASTVariableDefinitionList* args = node.GetArguments();
+ if (args) {
+ // Move the args to the symbol table entry
+ m_parent_scope->SetFunctionSignature(fun_id, args);
+ node.ClearArguments();
+
+ tListIterator<cASTVariableDefinition> it = args->Iterator();
+ cASTVariableDefinition* vd = NULL;
+ bool def_val_start = false;
+ while ((vd = it.Next())) {
+ vd->Accept(*this);
+ if (def_val_start) {
+ if (!vd->GetAssignmentExpression())
+ SEMANTIC_ERROR(FUNCTION_DEFAULT_REQUIRED, (const char*)vd->GetName(), (const char*)node.GetName());
+ } else {
+ if (vd->GetAssignmentExpression()) def_val_start = true;
+ }
+ }
+ }
+ } else {
+ if (m_parent_scope->GetFunctionRType(fun_id) != node.GetType())
+ SEMANTIC_ERROR(FUNCTION_RTYPE_MISMATCH, (const char*)node.GetName());
+
+ // Lookup previously defined symbol table
+ m_cur_symtbl = m_parent_scope->GetFunctionSymbolTable(fun_id);
+
+ // Verify that the call signatures match
+ cASTVariableDefinitionList* ssig = m_parent_scope->GetFunctionSignature(fun_id);
+ if (ssig && node.GetArguments()) {
+ if (ssig->GetSize() == node.GetArguments()->GetSize()) {
+ tListIterator<cASTVariableDefinition> sit = ssig->Iterator();
+ tListIterator<cASTVariableDefinition> nit = node.GetArguments()->Iterator();
+ while (true) {
+ cASTVariableDefinition* svd = sit.Next();
+ cASTVariableDefinition* nvd = nit.Next();
+ if (!svd || !nvd) break;
+
+ if (svd->GetName() != nvd->GetName() || svd->GetType() != nvd->GetType() || nvd->GetAssignmentExpression()) {
+ SEMANTIC_ERROR(FUNCTION_SIGNATURE_MISMATCH, (const char*)node.GetName());
+ break;
+ }
+ }
+ } else {
+ SEMANTIC_ERROR(FUNCTION_SIGNATURE_MISMATCH, (const char*)node.GetName());
+ }
+ } else if ((ssig && !node.GetArguments()) || (!ssig && node.GetArguments())) {
+ SEMANTIC_ERROR(FUNCTION_SIGNATURE_MISMATCH, (const char*)node.GetName());
+ }
+ }
+
+ // If this is the definition process the code
+ if (node.GetCode()) {
+ if (!m_parent_scope->GetFunctionDefinition(fun_id)) {
+ node.GetCode()->Accept(*this);
+
+ // Move the code to the symbol table entry
+ m_parent_scope->SetFunctionDefinition(fun_id, node.GetCode());
+ node.SetCode(NULL);
+ } else {
+ SEMANTIC_ERROR(FUNCTION_REDEFINITION, (const char*)node.GetName());
+ }
+ }
+
+ // Pop function stack
+ sFunctionEntry prev = m_fun_stack.Pop();
+ m_cur_symtbl = m_parent_scope;
+ m_parent_scope = prev.parent_scope;
+ m_fun_id = prev.fun_id;
}
@@ -558,16 +638,14 @@
-void cSemanticASTVisitor::reportError(bool fail, ASSemanticError_t err, const cASFilePosition& fp, const int line, ...)
+void cSemanticASTVisitor::reportError(ASSemanticError_t err, const cASFilePosition& fp, const int line, ...)
{
#define ERR_ENDL " (cSemanticASTVisitor.cc:" << line << ")" << std::endl
#define VA_ARG_STR va_arg(vargs, const char*)
- if (fail) m_success = false;
-
std::cerr << fp.GetFilename() << ":" << fp.GetLineNumber();
if (err < AS_SEMANTIC_WARN__LAST) std::cerr << ": warning: ";
- else std::cerr << ": error: ";
+ else { m_success = false; std::cerr << ": error: "; }
va_list vargs;
va_start(vargs, line);
@@ -585,6 +663,19 @@
case AS_SEMANTIC_ERR_CANNOT_CAST:
std::cerr << "cannot cast " << VA_ARG_STR << " to " << VA_ARG_STR << ERR_ENDL;
break;
+ case AS_SEMANTIC_ERR_FUNCTION_DEFAULT_REQUIRED:
+ std::cerr << "'" << VA_ARG_STR << "' argument of '" << VA_ARG_STR << "()' requires a default value due to previous"
+ << "argument defaults" << ERR_ENDL;
+ break;
+ case AS_SEMANTIC_ERR_FUNCTION_REDEFINITION:
+ std::cerr << "redefinition of '" << VA_ARG_STR << "()'" << ERR_ENDL;
+ break;
+ case AS_SEMANTIC_ERR_FUNCTION_RTYPE_MISMATCH:
+ std::cerr << "return type of '" << VA_ARG_STR << "()' does not match declaration" << ERR_ENDL;
+ break;
+ case AS_SEMANTIC_ERR_FUNCTION_SIGNATURE_MISMATCH:
+ std::cerr << "call signature of '" << VA_ARG_STR << "()' does not match declaration" << ERR_ENDL;
+ break;
case AS_SEMANTIC_ERR_TOO_MANY_ARGUMENTS:
std::cerr << "too many arguments" << ERR_ENDL;
break;
Modified: development/source/script/cSemanticASTVisitor.h
===================================================================
--- development/source/script/cSemanticASTVisitor.h 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/cSemanticASTVisitor.h 2008-02-29 21:54:46 UTC (rev 2402)
@@ -45,12 +45,13 @@
struct sFunctionEntry
{
- cSymbolTable* scope;
+ cSymbolTable* parent_scope;
int fun_id;
cSymbolTable* fun_symtbl;
- sFunctionEntry() : scope(NULL), fun_id(-1) { ; }
+ sFunctionEntry() : parent_scope(NULL), fun_id(-1) { ; }
+ sFunctionEntry(cSymbolTable* ps, int in_fun_id) : parent_scope(ps), fun_id(in_fun_id) { ; }
};
tSmartArray<sFunctionEntry> m_fun_stack;
@@ -98,6 +99,6 @@
inline bool lookupVariable(const cString& name, int& var_id, bool& global) const;
- void reportError(bool fail, ASSemanticError_t err, const cASFilePosition& fp, const int line, ...);
+ void reportError(ASSemanticError_t err, const cASFilePosition& fp, const int line, ...);
};
#endif
Modified: development/source/script/cSymbolTable.h
===================================================================
--- development/source/script/cSymbolTable.h 2008-02-29 16:51:56 UTC (rev 2401)
+++ development/source/script/cSymbolTable.h 2008-02-29 21:54:46 UTC (rev 2402)
@@ -26,10 +26,12 @@
#define cSymbolTable_h
#include "AvidaScript.h"
+#include "ASTree.h"
#include "tArray.h"
#include "tDictionary.h"
+
// Active/inactive functions and variables within the scope of the current function (or globally)
@@ -52,10 +54,15 @@
{
cString name;
ASType_t type;
+ cASTVariableDefinitionList* signature;
+ cSymbolTable* symtbl;
+ cASTNode* code;
bool active;
- sFunctionEntry(const cString& in_name, ASType_t in_type) : name(in_name), type(in_type), active(true) { ; }
+ sFunctionEntry(const cString& in_name, ASType_t in_type)
+ : name(in_name), type(in_type), signature(NULL), symtbl(NULL), code(NULL), active(true) { ; }
+ ~sFunctionEntry() { delete signature; delete symtbl; delete code; }
};
tArray<sFunctionEntry*> m_fun_tbl;
tDictionary<int> m_fun_dict;
@@ -73,17 +80,24 @@
bool AddVariable(const cString& name, ASType_t type, int& var_id);
bool AddFunction(const cString& name, ASType_t type, int& fun_id);
+ bool LookupVariable(const cString& name, int& var_id) { return m_sym_dict.Find(name, var_id); }
+ bool LookupFunction(const cString& name, int& fun_id) { return m_fun_dict.Find(name, fun_id); }
+
ASType_t GetVariableType(int var_id) const { return m_sym_tbl[var_id]->type; }
+
ASType_t GetFunctionRType(int fun_id) const { return m_fun_tbl[fun_id]->type; }
+ cSymbolTable* GetFunctionSymbolTable(int fun_id) { return m_fun_tbl[fun_id]->symtbl; }
+ cASTVariableDefinitionList* GetFunctionSignature(int fun_id) { return m_fun_tbl[fun_id]->signature; }
+ cASTNode* GetFunctionDefinition(int fun_id) { return m_fun_tbl[fun_id]->code; }
- bool LookupVariable(const cString& name, int& var_id) { return m_sym_dict.Find(name, var_id); }
- bool LookupFunction(const cString& name, int& fun_id) { return m_fun_dict.Find(name, fun_id); }
+ inline void SetFunctionSymbolTable(int fun_id, cSymbolTable* symtbl) { m_fun_tbl[fun_id]->symtbl = symtbl; }
+ inline void SetFunctionSignature(int fun_id, cASTVariableDefinitionList* vdl) { m_fun_tbl[fun_id]->signature = vdl; }
+ inline void SetFunctionDefinition(int fun_id, cASTNode* code) { m_fun_tbl[fun_id]->code = code; }
- inline bool HasSymbol(const cString& name) const { return m_sym_dict.HasEntry(name) || m_fun_dict.HasEntry(name); }
-
inline cString VariableNearMatch(const cString& name) const { return m_sym_dict.NearMatch(name); }
inline cString FunctionNearMatch(const cString& name) const { return m_fun_dict.NearMatch(name); }
};
+
#endif
More information about the Avida-cvs
mailing list