[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