Browse files

Added infrastructure for AST transformations

You can now create objects that optimize nodes, or adjust the syntax tree to generate one more specific instruction from several AST nodes.
  • Loading branch information...
1 parent 464b75f commit ce1a72a94ad631eaf38961f29bdac0666dbdea8c @uliwitness committed May 27, 2012
View
2 CCodeBlockNode.cpp
@@ -49,6 +49,8 @@ void CCodeBlockNodeBase::DebugPrintInner( std::ostream& destStream, size_t inden
void CCodeBlockNodeBase::Simplify()
{
+ CNode::Simplify();
+
std::vector<CNode*>::iterator itty;
for( itty = mCommands.begin(); itty != mCommands.end(); itty++ )
View
2 CCommandNode.cpp
@@ -42,6 +42,8 @@ void CCommandNode::AddParam( CValueNode* val )
void CCommandNode::Simplify()
{
+ CNode::Simplify();
+
std::vector<CValueNode*>::iterator itty;
for( itty = mParams.begin(); itty != mParams.end(); itty++ )
View
2 CFunctionCallNode.cpp
@@ -57,6 +57,8 @@ void CFunctionCallNode::AddParam( CValueNode* val )
void CFunctionCallNode::Simplify()
{
+ CValueNode::Simplify();
+
std::vector<CValueNode*>::iterator itty;
for( itty = mParams.begin(); itty != mParams.end(); itty++ )
View
2 CGlobalPropertyNode.cpp
@@ -43,6 +43,8 @@ void CGlobalPropertyNode::AddParam( CValueNode* val )
void CGlobalPropertyNode::Simplify()
{
+ CValueNode::Simplify();
+
std::vector<CValueNode*>::iterator itty;
for( itty = mParams.begin(); itty != mParams.end(); itty++ )
View
7 CMakeChunkConstNode.cpp
@@ -45,14 +45,7 @@ void CMakeChunkConstNode::GenerateCode( CCodeBlock* inCodeBlock )
(*itty)->GenerateCode( inCodeBlock );
}
- #if 0
- // We want to use GeneratePushChunkConstInstruction here, but for properties
- // we will need a chunk reference instead. +++ TODO: build non-const syntax
- // tree element if we see it's used by a property.
- inCodeBlock->GeneratePushChunkRefInstruction( BACK_OF_STACK, chunkType );
- #else
inCodeBlock->GeneratePushChunkConstInstruction( BACK_OF_STACK, chunkType );
- #endif
}
} // namespace Carlson
View
10 CMakeChunkRefNode.cpp
@@ -30,18 +30,16 @@ CValueNode* CMakeChunkRefNode::Copy()
void CMakeChunkRefNode::GenerateCode( CCodeBlock* inCodeBlock )
{
std::vector<CValueNode*>::const_iterator itty = mParams.begin();
- int16_t bpRelativeOffset = BACK_OF_STACK; // Means
CLocalVariableRefValueNode * theVar = dynamic_cast<CLocalVariableRefValueNode*>(*itty);
- if( theVar )
- bpRelativeOffset = theVar->GetBPRelativeOffset();
- else
+ if( !theVar )
{
- (*itty)->GenerateCode( inCodeBlock );
- bpRelativeOffset = BACK_OF_STACK;
+ throw std::runtime_error("Can't make chunks of this value.");
}
+ int16_t bpRelativeOffset = theVar->GetBPRelativeOffset();
+
itty++;
uint32_t chunkType = (*itty)->GetAsInt();
View
9 CNode.cpp
@@ -8,4 +8,13 @@
*/
#include "CNode.h"
+#include "CNodeTransformation.h"
+
+using namespace Carlson;
+
+
+void CNode::Simplify()
+{
+ CNodeTransformationBase::Apply( this );
+}
View
2 CNode.h
@@ -43,7 +43,7 @@ class CNode
explicit CNode( CParseTree* inTree ) : mParseTree(inTree) {};
virtual ~CNode() {};
- virtual void Simplify() {}; // For optimizing our parse tree before we actually generate code.
+ virtual void Simplify(); // For optimizing our parse tree before we actually generate code.
virtual void GenerateCode( CCodeBlock* inCodeBlock ) {}; // Generate the actual bytecode.
View
27 CNodeTransformation.cpp
@@ -0,0 +1,27 @@
+//
+// CNodeTransformation.cpp
+// Stacksmith
+//
+// Created by Uli Kusterer on 26.05.12.
+// Copyright (c) 2012 Uli Kusterer. All rights reserved.
+//
+
+#include "CNodeTransformation.h"
+
+
+namespace Carlson
+{
+
+std::vector<CNodeTransformationBase*> sNodeTransformations;
+
+
+void CNodeTransformationBase::Apply( CNode* inNode )
+{
+ std::vector<CNodeTransformationBase*>::const_iterator itty;
+ for( itty = sNodeTransformations.begin(); itty != sNodeTransformations.end(); itty++ )
+ {
+ (*itty)->Simplify_External( inNode );
+ }
+}
+
+}
View
75 CNodeTransformation.h
@@ -0,0 +1,75 @@
+//
+// CNodeTransformation.h
+// Stacksmith
+//
+// Created by Uli Kusterer on 26.05.12.
+// Copyright (c) 2012 Uli Kusterer. All rights reserved.
+//
+
+#pragma once
+
+/*
+ CNodeTransformation is a class that you can use to implement transformations
+ on a particular class of node. E.g. optimizations, or to detect certain
+ patterns and re-arrange nodes, like we do for properties on chunk expressions,
+ which get parsed naively, and then later transformed into the proper
+ nodes.
+
+ We could do this in CNode's Simplify() directly, but this way each node only
+ needs to know about itself, and ONLY transformations need to know about the
+ other nodes they operate on. Moreover, each transformation can be its own
+ file and only THAT has its dependencies.
+*/
+
+#include "CNode.h"
+#include <vector>
+
+
+namespace Carlson
+{
+
+
+// Base class for transformations: (Generally you want CNodeTransformation below!)
+
+class CNodeTransformationBase
+{
+public:
+ virtual ~CNodeTransformationBase() {};
+
+ virtual void Simplify_External( CNode *inNode ) = 0;
+
+ static void Apply( CNode* inNode );
+};
+
+
+extern std::vector<CNodeTransformationBase*> sNodeTransformations;
+
+
+/*
+ CNodeTransformation is templated based on the class of the node to operate
+ on. Call Initialize some time at startup to register, override Simplify().
+*/
+
+template <class c_node_subclass>
+class CNodeTransformation
+{
+public:
+ virtual ~CNodeTransformation() {};
+
+ virtual void Simplify( c_node_subclass * inNode ) = 0;
+
+ virtual void Simplify_External( CNode *inNode )
+ {
+ c_node_subclass * subclassPtr = dynamic_cast<c_node_subclass*>(inNode);
+
+ if( subclassPtr )
+ {
+ Simplify( subclassPtr );
+ }
+ }
+
+ static void Initialize() { sNodeTransformations.push_back( new CNodeTransformation<c_node_subclass> ); };
+};
+
+
+} // Carlson
View
2 CObjectPropertyNode.cpp
@@ -58,6 +58,8 @@ void CObjectPropertyNode::AddParam( CValueNode* val )
void CObjectPropertyNode::Simplify()
{
+ CValueNode::Simplify();
+
std::vector<CValueNode*>::iterator itty;
for( itty = mParams.begin(); itty != mParams.end(); itty++ )
View
6 COperatorNode.cpp
@@ -57,6 +57,8 @@ CValueNode* COperatorNode::Copy()
void COperatorNode::Simplify()
{
+ CValueNode::Simplify();
+
std::vector<CValueNode*>::iterator itty;
for( itty = mParams.begin(); itty != mParams.end(); itty++ )
@@ -65,11 +67,11 @@ void COperatorNode::Simplify()
switch( mInstructionID )
{
case CONCATENATE_VALUES_INSTR:
-
+ // +++
break;
case CONCATENATE_VALUES_WITH_SPACE_INSTR:
-
+ // +++
break;
}
}
View
2 CValueNode.cpp
@@ -54,6 +54,8 @@ CLocalVariableRefValueNode::CLocalVariableRefValueNode( CParseTree* inTree, CCod
void CLocalVariableRefValueNode::Simplify()
{
GetBPRelativeOffset(); // Make sure we are assigned a slot NOW, so we know how many variables we need by the time we generate the function prolog.
+
+ CNode::Simplify();
}
View
4 CValueNode.h
@@ -36,9 +36,7 @@ class CValueNode : public CNode
virtual size_t GetLineNum() { return 0; };
virtual void GenerateCode( CCodeBlock* inCodeBlock ) {}; // Generate the actual bytecode so it leaves the result on the stack.
-
- virtual void Simplify() {};
-
+
virtual bool IsConstant() { return false; };
virtual CValueNode* Copy() { return NULL; };

0 comments on commit ce1a72a

Please sign in to comment.