1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
#pragma once
#include "Compiler/NamedThread.h"
#include "Compiler/Function.h"
#include "Compiler/Syntax/SStr.h"
#include "Compiler/Syntax/Node.h"
#include "Compiler/Doc.h"
#include "Return.h"
#include "Decl.h"
#include "Param.h"
#include "Block.h"
namespace storm {
namespace bs {
STORM_PKG(lang.bs);
class FnBody;
class BSFunction;
/**
* Function declaration. This holds the needed information to create each function later
* on. Also acts as an intermediate store for types until we have found all types in the
* current package. Otherwise, we would behave like C, that the type declarations have to be
* before anything that uses them.
*
* If 'result' is null, then we assume that this function declares a setter function, since
* the return type is always 'null' for them.
*/
class FunctionDecl : public NamedDecl {
STORM_CLASS;
public:
STORM_CTOR FunctionDecl(SrcPos pos,
Scope scope,
MAYBE(SrcName *) result,
syntax::SStr *name,
Array<NameParam> *params,
syntax::Node *options,
syntax::Node *body);
// Values.
SrcPos pos;
Scope scope;
syntax::SStr *name;
MAYBE(SrcName *) result;
Array<NameParam> *params;
MAYBE(syntax::Node *) options;
syntax::Node *body;
// Temporary solution for updating a function.
virtual MAYBE(Named *) STORM_FN update(Scope scope);
void STORM_FN update(BSFunction *fn);
// Get our name as a NamePart.
NamePart *STORM_FN namePart() const;
// To string.
virtual void STORM_FN toS(StrBuf *to) const;
private:
// Create the actual function.
virtual Named *STORM_FN doCreate();
};
// Declare setter functions.
FunctionDecl *STORM_FN assignDecl(SrcPos pos,
Scope scope,
syntax::SStr *name,
Array<NameParam> *params,
syntax::Node *options,
syntax::Node *body);
/**
* Raw function that will not read syntax trees by parsing a string.
*/
class BSRawFn : public Function {
STORM_CLASS;
public:
// Create.
STORM_CTOR BSRawFn(Value result, syntax::SStr *name, Array<ValParam> *params, MAYBE(NamedThread *) thread);
// Set the thread for this function. Should be done before code is generated for the
// first time, and before someone else start depending on this function.
void STORM_FN thread(Scope scope, SrcName *name);
// Override this to create the syntax tree to compile. Expected to work until 'clearBody' is called.
// TODO: Mark as abstract.
virtual FnBody *STORM_FN createBody();
// Called when we know we don't need the body anymore, i.e. 'createBody' may stop
// returning sensible results.
virtual void STORM_FN clearBody();
// Make this function static by removing the 'this' parameter. Only do this before the
// function is added to the name tree!
void STORM_FN makeStatic();
// Make the function inlineable. Only has affect before the function is compiled.
void STORM_FN makeInline();
// Add function parameters to a block. Mainly for internal use.
Array<LocalVar *> *STORM_FN addParams(Block *block);
// Get parameters as required by documentation.
Array<DocParam> *STORM_FN docParams();
protected:
// Parameter names and values.
Array<ValParam> *valParams;
// Re-compile at next execution.
void STORM_FN reset();
// Override if you want to create a CodeGen object yourself.
virtual CodeGen *STORM_FN createRawBody();
private:
// Generate code.
CodeGen *CODECALL generateCode();
// Generate code for inline usage.
void CODECALL generateInlineCode(InlineParams params);
// Initialize.
void init(NamedThread *thread);
// Remember if we have cleared body data.
Bool bodyCleared;
// Should we be an inline function?
Bool isInline;
};
/**
* Function in the BS language.
*/
class BSFunction : public BSRawFn {
STORM_CLASS;
public:
// Create a function.
STORM_CTOR BSFunction(Value result, syntax::SStr *name, Array<ValParam> *params, Scope scope,
MAYBE(NamedThread *) thread, syntax::Node *body);
// Scope.
Scope scope;
// Code.
MAYBE(syntax::Node *) body;
// Create the body from our string.
virtual FnBody *STORM_FN createBody();
virtual void STORM_FN clearBody();
// Temporary solution for updating a function.
Bool STORM_FN update(Array<ValParam> *params, syntax::Node *body, SrcPos pos);
Bool STORM_FN update(Array<ValParam> *params, syntax::Node *body);
Bool STORM_FN update(Array<Str *> *params, syntax::Node *body);
Bool STORM_FN update(BSFunction *from);
};
/**
* Function using a pre-created syntax tree.
*/
class BSTreeFn : public BSRawFn {
STORM_CLASS;
public:
// Create.
STORM_CTOR BSTreeFn(Value result, syntax::SStr *name, Array<ValParam> *params, MAYBE(NamedThread *) thread);
// Set the root of the syntax tree. Resetting the body also makes the function re-compile.
void STORM_ASSIGN body(FnBody *body);
// Override to use the body.
virtual FnBody *STORM_FN createBody();
virtual void STORM_FN clearBody();
private:
// Body.
MAYBE(FnBody *) root;
};
/**
* Abstract function that throws an exception when invoked.
*/
class BSAbstractFn : public BSRawFn {
STORM_CLASS;
public:
STORM_CTOR BSAbstractFn(Value result, syntax::SStr *name, Array<ValParam> *params);
protected:
// Override to use the body.
virtual CodeGen *STORM_FN createRawBody();
};
/**
* Body of a function.
*/
class FnBody : public ExprBlock {
STORM_CLASS;
public:
STORM_CTOR FnBody(BSRawFn *owner, Scope scope);
STORM_CTOR FnBody(BSFunction *owner);
// Parameters, ordered as they appear in the list of formal parameters.
Array<LocalVar *> *parameters;
// Lookup information.
ReturnInfo *info;
// Get the type.
Value STORM_FN type() const { return info->type; }
// We don't need to create a separate block for the function body itself, we can just
// use the root block.
virtual void STORM_FN code(CodeGen *state, CodeResult *to);
};
}
}
|