🧠 Feature: Meta-programming engine (#10)
* Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages
This commit is contained in:
parent
c65c41eed2
commit
39508a5907
|
@ -17,3 +17,4 @@ dub.selections.json
|
|||
# Documentation )generated)
|
||||
docs/
|
||||
docs.json
|
||||
desktop_dev.code-workspace
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 428 KiB |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
Binary file not shown.
|
@ -189,4 +189,43 @@ public final class CompilerConfiguration
|
|||
ConfigEntry _discard;
|
||||
return hasConfig_internal(key, _discard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the default compiler configuration
|
||||
*
|
||||
* Returns: a `CompilerConfguration`
|
||||
*/
|
||||
public static CompilerConfiguration defaultConfig()
|
||||
{
|
||||
/* Generate a fresh new config */
|
||||
CompilerConfiguration config = new CompilerConfiguration();
|
||||
|
||||
/* Enable Behaviour-C fixes */
|
||||
config.addConfig(ConfigEntry("behavec:preinline_args", true));
|
||||
|
||||
/* Enable pretty code generation for DGen */
|
||||
config.addConfig(ConfigEntry("dgen:pretty_code", true));
|
||||
|
||||
/* Enable entry point test generation for DGen */
|
||||
config.addConfig(ConfigEntry("dgen:emit_entrypoint_test", true));
|
||||
|
||||
/* Set the mapping to hashing of entity names (TODO: This should be changed before release) */
|
||||
config.addConfig(ConfigEntry("emit:mapper", "hashmapper"));
|
||||
|
||||
/**
|
||||
* Configure, at compile time, the system type aliases
|
||||
*/
|
||||
version(X86)
|
||||
{
|
||||
/* Set maximum width to 4 bytes (32-bits) */
|
||||
config.addConfig(ConfigEntry("types:max_width", 4));
|
||||
}
|
||||
else version(X86_64)
|
||||
{
|
||||
/* Set maximum width to 8 bytes (64-bits) */
|
||||
config.addConfig(ConfigEntry("types:max_width", 8));
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
|
@ -115,21 +115,6 @@ public class Compiler
|
|||
/* The configuration */
|
||||
private CompilerConfiguration config;
|
||||
|
||||
/* TODO: Make the default config */
|
||||
private void defaultConfig()
|
||||
{
|
||||
/* Enable Behaviour-C fixes */
|
||||
config.addConfig(ConfigEntry("behavec:preinline_args", true));
|
||||
|
||||
/* Enable pretty code generation for DGen */
|
||||
config.addConfig(ConfigEntry("dgen:pretty_code", true));
|
||||
|
||||
/* Enable entry point test generation for DGen */
|
||||
config.addConfig(ConfigEntry("dgen:emit_entrypoint_test", true));
|
||||
|
||||
/* Set the mapping to hashing of entity names (TODO: This should be changed before release) */
|
||||
config.addConfig(ConfigEntry("emit:mapper", "hashmapper"));
|
||||
}
|
||||
|
||||
public CompilerConfiguration getConfig()
|
||||
{
|
||||
|
@ -147,10 +132,8 @@ public class Compiler
|
|||
this.inputSource = sourceCode;
|
||||
this.emitOutFile = emitOutFile;
|
||||
|
||||
this.config = new CompilerConfiguration();
|
||||
|
||||
/* Enable the default config */
|
||||
defaultConfig();
|
||||
/* Get the default config */
|
||||
this.config = CompilerConfiguration.defaultConfig();
|
||||
}
|
||||
|
||||
/* Setup the lexer and begin lexing */
|
||||
|
@ -207,7 +190,7 @@ public class Compiler
|
|||
throw new CompilerException(CompilerError.PARSE_NOT_YET_PERFORMED);
|
||||
}
|
||||
|
||||
this.typeChecker = new TypeChecker(modulle);
|
||||
this.typeChecker = new TypeChecker(modulle, config);
|
||||
|
||||
/* Perform typechecking/codegen */
|
||||
this.typeChecker.beginCheck();
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
module tlang.compiler.parsing.cloneable;
|
||||
|
||||
import tlang.compiler.symbols.data : Statement;
|
||||
|
||||
/**
|
||||
* A parse-node/AST-node which implements `Cloneable` can
|
||||
* be safely deeply cloned such that a full copy is returned.
|
||||
*/
|
||||
public interface Cloneable
|
||||
{
|
||||
/**
|
||||
* Performs a deep clone of this parse node
|
||||
*
|
||||
* Returns: the clone
|
||||
*/
|
||||
public Statement clone();
|
||||
}
|
|
@ -64,6 +64,12 @@ public enum SymbolType
|
|||
EXTERN,
|
||||
EXTERN_EFUNC,
|
||||
EXTERN_EVAR,
|
||||
|
||||
/**
|
||||
* `generic`
|
||||
*/
|
||||
GENERIC_TYPE_DECLARE,
|
||||
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
|
@ -380,6 +386,11 @@ public SymbolType getSymbolType(Token tokenIn)
|
|||
{
|
||||
return SymbolType.DISCARD;
|
||||
}
|
||||
/* generic keyword */
|
||||
else if(cmp(token, "generic") == 0)
|
||||
{
|
||||
return SymbolType.GENERIC_TYPE_DECLARE;
|
||||
}
|
||||
/* An identifier/type (of some sorts) - further inspection in parser is needed */
|
||||
else if(isPathIdentifier(token) || isIdentifier(token))
|
||||
{
|
||||
|
|
|
@ -29,7 +29,9 @@ public Statement[] weightReorder(Statement[] statements)
|
|||
return stmntsRed;
|
||||
}
|
||||
|
||||
public interface Container
|
||||
// TODO: Honestly all contains should be a kind-of `MStatementSearchable` and `MStatementReplaceable`
|
||||
import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable, MStatementReplaceable;
|
||||
public interface Container : MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
public void addStatement(Statement statement);
|
||||
|
||||
|
@ -38,6 +40,7 @@ public interface Container
|
|||
public Statement[] getStatements();
|
||||
}
|
||||
|
||||
|
||||
public class Module : Entity, Container
|
||||
{
|
||||
this(string moduleName)
|
||||
|
@ -62,6 +65,79 @@ public class Module : Entity, Container
|
|||
{
|
||||
return weightReorder(statements);
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on each `Statement` making up our body */
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
foreach(Statement curStmt; getStatements())
|
||||
{
|
||||
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
||||
if(curStmtCasted)
|
||||
{
|
||||
matches ~= curStmtCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If not ourself, then check the body statements */
|
||||
else
|
||||
{
|
||||
/**
|
||||
* First check each `Statement` that make sup our
|
||||
* body and see if we can replace that, else see
|
||||
* if we can recurse on each of the body statements
|
||||
* and apply replacement therein
|
||||
*/
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
Statement[] bodyStmts = getStatements();
|
||||
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
||||
{
|
||||
Statement curBodyStmt = bodyStmts[idx];
|
||||
|
||||
/* Should we directly replace the Statement in the body? */
|
||||
if(curBodyStmt == thiz)
|
||||
{
|
||||
// Replace the statement in the body
|
||||
statements[idx] = that;
|
||||
|
||||
// Re-parent `that` to us
|
||||
that.parentTo(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
/* If we cannot, then recurse (try) on it */
|
||||
else if(cast(MStatementReplaceable)curBodyStmt)
|
||||
{
|
||||
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
||||
if(curBodyStmtRepl.replace(thiz, that))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,6 +170,79 @@ public class Struct : Type, Container
|
|||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on each `Statement` making up our body */
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
foreach(Statement curStmt; getStatements())
|
||||
{
|
||||
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
||||
if(curStmtCasted)
|
||||
{
|
||||
matches ~= curStmtCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If not ourself, then check the body statements */
|
||||
else
|
||||
{
|
||||
/**
|
||||
* First check each `Statement` that make sup our
|
||||
* body and see if we can replace that, else see
|
||||
* if we can recurse on each of the body statements
|
||||
* and apply replacement therein
|
||||
*/
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
Statement[] bodyStmts = getStatements();
|
||||
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
||||
{
|
||||
Statement curBodyStmt = bodyStmts[idx];
|
||||
|
||||
/* Should we directly replace the Statement in the body? */
|
||||
if(curBodyStmt == thiz)
|
||||
{
|
||||
// Replace the statement in the body
|
||||
statements[idx] = that;
|
||||
|
||||
// Re-parent `that` to us
|
||||
that.parentTo(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
/* If we cannot, then recurse (try) on it */
|
||||
else if(cast(MStatementReplaceable)curBodyStmt)
|
||||
{
|
||||
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
||||
if(curBodyStmtRepl.replace(thiz, that))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Clazz : Type, Container
|
||||
|
@ -139,5 +288,78 @@ public class Clazz : Type, Container
|
|||
{
|
||||
return weightReorder(statements);
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on each `Statement` making up our body */
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
foreach(Statement curStmt; getStatements())
|
||||
{
|
||||
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
||||
if(curStmtCasted)
|
||||
{
|
||||
matches ~= curStmtCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If not ourself, then check the body statements */
|
||||
else
|
||||
{
|
||||
/**
|
||||
* First check each `Statement` that make sup our
|
||||
* body and see if we can replace that, else see
|
||||
* if we can recurse on each of the body statements
|
||||
* and apply replacement therein
|
||||
*/
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
Statement[] bodyStmts = getStatements();
|
||||
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
||||
{
|
||||
Statement curBodyStmt = bodyStmts[idx];
|
||||
|
||||
/* Should we directly replace the Statement in the body? */
|
||||
if(curBodyStmt == thiz)
|
||||
{
|
||||
// Replace the statement in the body
|
||||
statements[idx] = that;
|
||||
|
||||
// Re-parent `that` to us
|
||||
that.parentTo(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
/* If we cannot, then recurse (try) on it */
|
||||
else if(cast(MStatementReplaceable)curBodyStmt)
|
||||
{
|
||||
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
||||
if(curBodyStmtRepl.replace(thiz, that))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -215,7 +215,8 @@ public class Entity : Statement
|
|||
}
|
||||
|
||||
/* TODO: DO we need intermediary class, TypedEntity */
|
||||
public class TypedEntity : Entity
|
||||
import tlang.compiler.symbols.mcro : MTypeRewritable;
|
||||
public class TypedEntity : Entity, MTypeRewritable
|
||||
{
|
||||
private string type;
|
||||
|
||||
|
@ -230,6 +231,11 @@ public class TypedEntity : Entity
|
|||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(string type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public import tlang.compiler.symbols.containers;
|
||||
|
@ -352,9 +358,93 @@ public class Function : TypedEntity, Container
|
|||
|
||||
return "Function (Name: "~name~", ReturnType: "~type~", Args: "~argTypes~")";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on each `Statement` making up our body */
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
foreach(Statement curStmt; getStatements())
|
||||
{
|
||||
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
||||
if(curStmtCasted)
|
||||
{
|
||||
matches ~= curStmtCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If not ourself, then check the body statements */
|
||||
else
|
||||
{
|
||||
/**
|
||||
* First check each `Statement` that make sup our
|
||||
* body and see if we can replace that, else see
|
||||
* if we can recurse on each of the body statements
|
||||
* and apply replacement therein
|
||||
*/
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
Statement[] bodyStmts = getStatements();
|
||||
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
||||
{
|
||||
Statement curBodyStmt = bodyStmts[idx];
|
||||
|
||||
/* Should we directly replace the Statement in the body? */
|
||||
if(curBodyStmt == thiz)
|
||||
{
|
||||
// Replace the statement in the body
|
||||
// NOTE: The respective Variable Param must be swapped out too if need be
|
||||
// (varParams[] subsetOf Statements[])
|
||||
for(ulong varParamIdx = 0; varParamIdx < params.length; varParamIdx++)
|
||||
{
|
||||
VariableParameter curVarParam = params[varParamIdx];
|
||||
if(curVarParam == thiz)
|
||||
{
|
||||
params[varParamIdx] = cast(VariableParameter)that;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bodyStatements[idx] = that;
|
||||
|
||||
// Re-parent `that` to us
|
||||
that.parentTo(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
/* If we cannot, then recurse (try) on it */
|
||||
else if(cast(MStatementReplaceable)curBodyStmt)
|
||||
{
|
||||
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
||||
if(curBodyStmtRepl.replace(thiz, that))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Variable : TypedEntity
|
||||
public class Variable : TypedEntity, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
/* TODO: Just make this an Expression */
|
||||
private VariableAssignment assignment;
|
||||
|
@ -382,6 +472,49 @@ public class Variable : TypedEntity
|
|||
{
|
||||
return "Variable (Ident: "~name~", Type: "~type~")";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/**
|
||||
* Recurse on the `VariableAssignment`
|
||||
*/
|
||||
MStatementSearchable innerStmt = cast(MStatementSearchable)assignment;
|
||||
if(innerStmt)
|
||||
{
|
||||
matches ~= innerStmt.search(clazzType);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we, the `Variable`, are the `thiz` then we cannot perform replacement */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* Check if we should replace the `VariableAssignment` */
|
||||
else if(thiz == assignment)
|
||||
{
|
||||
assignment = cast(VariableAssignment)that;
|
||||
return true;
|
||||
}
|
||||
/* Recurse on the variable assignment */
|
||||
else
|
||||
{
|
||||
return assignment.replace(thiz, that);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -394,7 +527,7 @@ public import tlang.compiler.symbols.expressions;
|
|||
/**
|
||||
* TODO: Rename to `VariableDeclarationAssignment`
|
||||
*/
|
||||
public class VariableAssignment : Statement
|
||||
public class VariableAssignment : Statement, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
private Expression expression;
|
||||
private Variable variable;
|
||||
|
@ -414,6 +547,8 @@ public class VariableAssignment : Statement
|
|||
return variable;
|
||||
}
|
||||
|
||||
// NOTE-to-self: Very interesting method we have here, is this just for debugging?
|
||||
// (15th May 2023, whilst working on Meta)
|
||||
public void setVariable(Variable variable)
|
||||
{
|
||||
this.variable = variable;
|
||||
|
@ -423,12 +558,60 @@ public class VariableAssignment : Statement
|
|||
{
|
||||
return "[varAssignDec'd: To: "~variable.toString()~"]";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on our `Expression` (if possible) */
|
||||
MStatementSearchable innerStmt = cast(MStatementSearchable)expression;
|
||||
if(innerStmt)
|
||||
{
|
||||
matches ~= innerStmt.search(clazzType);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* We cannot replace ourselves directly */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* Is the `Expression` the `thiz`, then swap out the expression */
|
||||
else if(expression == thiz)
|
||||
{
|
||||
// TODO: Any reparenting needed?
|
||||
expression = cast(Expression)that;
|
||||
return true;
|
||||
}
|
||||
/* Recurse on the `Expression` being assigned (if possible) */
|
||||
else if(cast(MStatementReplaceable)expression)
|
||||
{
|
||||
MStatementReplaceable replStmt = cast(MStatementReplaceable)expression;
|
||||
return replStmt.replace(thiz, that);
|
||||
}
|
||||
/* If not matched */
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Rename to ``
|
||||
*/
|
||||
public class VariableAssignmentStdAlone : Statement
|
||||
public class VariableAssignmentStdAlone : Statement, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
private Expression expression;
|
||||
private string varName;
|
||||
|
@ -456,6 +639,55 @@ public class VariableAssignmentStdAlone : Statement
|
|||
{
|
||||
return "[varAssignStdAlone: To: "~varName~"]";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/**
|
||||
* Recurse on the assigned `Expression`
|
||||
*/
|
||||
MStatementSearchable assignedStmtCasted = cast(MStatementSearchable)expression;
|
||||
if(assignedStmtCasted)
|
||||
{
|
||||
matches ~= assignedStmtCasted.search(clazzType);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we, the `VariableAssignmentStdAlone`, are the `thiz` then we cannot perform replacement */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* Check if we should replace the `Expression` being assigned? */
|
||||
else if(thiz == expression)
|
||||
{
|
||||
expression = cast(Expression)that;
|
||||
return true;
|
||||
}
|
||||
/* Recurse on the assigned `Expression` (if possible) */
|
||||
else if(cast(MStatementReplaceable)expression)
|
||||
{
|
||||
MStatementReplaceable expressionCasted = cast(MStatementReplaceable)expression;
|
||||
return expressionCasted.replace(thiz, that);
|
||||
}
|
||||
/* None */
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add an ArrayAssignment thing here, would be similiar to PointerDeference
|
||||
|
@ -538,12 +770,8 @@ public class PointerDereferenceAssignment : Statement
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public class IdentExpression : Expression
|
||||
public class IdentExpression : Expression, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
|
||||
|
||||
|
||||
/* name */
|
||||
private string name;
|
||||
|
||||
|
@ -561,6 +789,27 @@ public class IdentExpression : Expression
|
|||
{
|
||||
name = newName;
|
||||
}
|
||||
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
// Nothing to replace within us
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class VariableExpression : IdentExpression
|
||||
|
@ -596,7 +845,8 @@ public class Call : IdentExpression
|
|||
}
|
||||
}
|
||||
|
||||
public final class FunctionCall : Call
|
||||
// FIXME: Finish adding proper `MStatementSearchable` and `MStatementReplaceable` to `FunctionCall`
|
||||
public final class FunctionCall : Call, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
/* Whether this is statement-level function call or not */
|
||||
|
||||
|
@ -644,6 +894,61 @@ public final class FunctionCall : Call
|
|||
{
|
||||
return isStatementLevel;
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
// TODO: Implement me
|
||||
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/**
|
||||
* Recurse on each `Expression` (if possible)
|
||||
*/
|
||||
foreach(Expression callExp; arguments)
|
||||
{
|
||||
MStatementSearchable innerStmt = cast(MStatementSearchable)callExp;
|
||||
if(innerStmt)
|
||||
{
|
||||
matches ~= innerStmt.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
// TODO: Implement me
|
||||
|
||||
// /* Check if our `Expression` matches, then replace */
|
||||
// if(expression == thiz)
|
||||
// {
|
||||
// // NOTE: This legit makes no sense and won't do anything, we could remove this
|
||||
// // and honestly should probably make this return false
|
||||
// // FIXME: Make this return `false` (see above)
|
||||
// expression = cast(Expression)that;
|
||||
// return true;
|
||||
// }
|
||||
// /* If not direct match, then recurse and replace (if possible) */
|
||||
// else if(cast(MStatementReplaceable)expression)
|
||||
// {
|
||||
// MStatementReplaceable replStmt = cast(MStatementReplaceable)expression;
|
||||
// return replStmt.replace(thiz, that);
|
||||
// }
|
||||
// /* If not direct match and not replaceable */
|
||||
// else
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -717,6 +1022,70 @@ public final class IfStatement : Entity, Container
|
|||
{
|
||||
return "IfStmt";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Loop through each `Branch` and recurse on them */
|
||||
foreach(Branch curBranch; branches)
|
||||
{
|
||||
matches ~= curBranch.search(clazzType);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If not ourself, then check each `Branch` or recurse on them */
|
||||
else
|
||||
{
|
||||
/**
|
||||
* First check each `Branch` that makes up our
|
||||
* branches array and see if we can replace that,
|
||||
* else see if we can recurse on each of the branche
|
||||
* and apply replacement therein
|
||||
*/
|
||||
Statement[] bodyStmts = getStatements();
|
||||
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
||||
{
|
||||
Statement curBodyStmt = bodyStmts[idx];
|
||||
|
||||
/* Should we directly replace the Statement in the body? */
|
||||
if(curBodyStmt == thiz)
|
||||
{
|
||||
// Replace the statement in the body
|
||||
// FIXME: Apply parenting? Yes we should
|
||||
branches[idx] = cast(Branch)that;
|
||||
return true;
|
||||
}
|
||||
/* If we cannot, then recurse (try) on it */
|
||||
else if(cast(MStatementReplaceable)curBodyStmt)
|
||||
{
|
||||
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
||||
if(curBodyStmtRepl.replace(thiz, that))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -785,6 +1154,50 @@ public final class WhileLoop : Entity, Container
|
|||
{
|
||||
return "WhileLoop";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on the the `Branch` */
|
||||
if(cast(MStatementSearchable)branch)
|
||||
{
|
||||
MStatementSearchable branchCasted = cast(MStatementSearchable)branch;
|
||||
if(branchCasted)
|
||||
{
|
||||
matches ~= branchCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If the `Branch` is to be replaced */
|
||||
else if(branch == thiz)
|
||||
{
|
||||
branch = cast(Branch)that;
|
||||
return true;
|
||||
}
|
||||
/* If not ourself, then recurse on the `Branch` */
|
||||
else
|
||||
{
|
||||
return branch.replace(thiz, that);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ForLoop : Entity, Container
|
||||
|
@ -872,6 +1285,66 @@ public final class ForLoop : Entity, Container
|
|||
{
|
||||
return "ForLoop";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on the pre-loop `Statement` */
|
||||
if(cast(MStatementSearchable)preLoopStatement)
|
||||
{
|
||||
MStatementSearchable preLoopStatementCasted = cast(MStatementSearchable)preLoopStatement;
|
||||
if(preLoopStatementCasted)
|
||||
{
|
||||
matches ~= preLoopStatementCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recurse on the the `Branch` */
|
||||
if(cast(MStatementSearchable)branch)
|
||||
{
|
||||
MStatementSearchable branchCasted = cast(MStatementSearchable)branch;
|
||||
if(branchCasted)
|
||||
{
|
||||
matches ~= branchCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If the `Branch` is to be replaced */
|
||||
else if(branch == thiz)
|
||||
{
|
||||
branch = cast(Branch)that;
|
||||
return true;
|
||||
}
|
||||
/* If the pre-loop `Statement` is to be replaced */
|
||||
else if(preLoopStatement == thiz)
|
||||
{
|
||||
preLoopStatement = cast(Statement)that;
|
||||
return true;
|
||||
}
|
||||
/* If not ourself, then recurse on the `Branch` */
|
||||
else
|
||||
{
|
||||
return branch.replace(thiz, that);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -954,9 +1427,97 @@ public final class Branch : Entity, Container
|
|||
{
|
||||
return "Branch";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on the branch condition `Expression` */
|
||||
if(cast(MStatementSearchable)branchCondition)
|
||||
{
|
||||
MStatementSearchable branchConditionCasted = cast(MStatementSearchable)branchCondition;
|
||||
if(branchConditionCasted)
|
||||
{
|
||||
matches ~= branchConditionCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recurse on each `Statement` making up our body */
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
foreach(Statement curStmt; getStatements())
|
||||
{
|
||||
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
||||
if(curStmtCasted)
|
||||
{
|
||||
matches ~= curStmtCasted.search(clazzType);
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* If we (`this`) are `thiz`, then we cannot replace */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* If the branch condition `Expression` is matching */
|
||||
else if(branchCondition == thiz)
|
||||
{
|
||||
branchCondition = cast(Expression)that;
|
||||
return true;
|
||||
}
|
||||
/* If not ourself, then check the body statements */
|
||||
else
|
||||
{
|
||||
/**
|
||||
* First check each `Statement` that make sup our
|
||||
* body and see if we can replace that, else see
|
||||
* if we can recurse on each of the body statements
|
||||
* and apply replacement therein
|
||||
*/
|
||||
// NOTE: Using weight-reordered? Is that fine?
|
||||
Statement[] bodyStmts = getStatements();
|
||||
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
||||
{
|
||||
Statement curBodyStmt = bodyStmts[idx];
|
||||
|
||||
/* Should we directly replace the Statement in the body? */
|
||||
if(curBodyStmt == thiz)
|
||||
{
|
||||
// Replace the statement in the body
|
||||
// FIXME: Apply parenting? Yes we should
|
||||
branchBody[idx] = that;
|
||||
return true;
|
||||
}
|
||||
/* If we cannot, then recurse (try) on it */
|
||||
else if(cast(MStatementReplaceable)curBodyStmt)
|
||||
{
|
||||
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
||||
if(curBodyStmtRepl.replace(thiz, that))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class DiscardStatement : Statement
|
||||
import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable;
|
||||
|
||||
public final class DiscardStatement : Statement, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
private Expression expression;
|
||||
|
||||
|
@ -977,6 +1538,54 @@ public final class DiscardStatement : Statement
|
|||
{
|
||||
return "[DiscardStatement: (Exp: "~expression.toString()~")]";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on our `Expression` (if possible) */
|
||||
MStatementSearchable innerStmt = cast(MStatementSearchable)expression;
|
||||
if(innerStmt)
|
||||
{
|
||||
matches ~= innerStmt.search(clazzType);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
import std.stdio;
|
||||
writeln("Replace() enter discard");
|
||||
|
||||
/* Check if our `Expression` matches, then replace */
|
||||
if(expression == thiz)
|
||||
{
|
||||
// NOTE: This legit makes no sense and won't do anything, we could remove this
|
||||
// and honestly should probably make this return false
|
||||
// FIXME: Make this return `false` (see above)
|
||||
expression = cast(Expression)that;
|
||||
return true;
|
||||
}
|
||||
/* If not direct match, then recurse and replace (if possible) */
|
||||
else if(cast(MStatementReplaceable)expression)
|
||||
{
|
||||
MStatementReplaceable replStmt = cast(MStatementReplaceable)expression;
|
||||
return replStmt.replace(thiz, that);
|
||||
}
|
||||
/* If not direct match and not replaceable */
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ExternStmt : Statement
|
||||
|
|
|
@ -56,7 +56,9 @@ public class UnaryOperatorExpression : OperatorExpression
|
|||
}
|
||||
}
|
||||
|
||||
public class BinaryOperatorExpression : OperatorExpression
|
||||
import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable;
|
||||
|
||||
public class BinaryOperatorExpression : OperatorExpression, MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
private Expression lhs, rhs;
|
||||
|
||||
|
@ -83,6 +85,72 @@ public class BinaryOperatorExpression : OperatorExpression
|
|||
/* TODO: FIll in */
|
||||
return "[BinOpExp: Op: "~to!(string)(operator)~", Lhs: "~lhs.toString()~", Rhs: "~rhs.toString()~"]";
|
||||
}
|
||||
|
||||
public override Statement[] search(TypeInfo_Class clazzType)
|
||||
{
|
||||
/* List of returned matches */
|
||||
Statement[] matches;
|
||||
|
||||
/* Are we (ourselves) of this type? */
|
||||
if(clazzType.isBaseOf(this.classinfo))
|
||||
{
|
||||
matches ~= [this];
|
||||
}
|
||||
|
||||
/* Recurse on our left-hand side `Expression` (if possible) */
|
||||
MStatementSearchable lhsCasted = cast(MStatementSearchable)lhs;
|
||||
if(lhsCasted)
|
||||
{
|
||||
matches ~= lhsCasted.search(clazzType);
|
||||
}
|
||||
|
||||
/* Recurse on our right-hand side `Expression` (if possible) */
|
||||
MStatementSearchable rhsCasted = cast(MStatementSearchable)rhs;
|
||||
if(rhsCasted)
|
||||
{
|
||||
matches ~= rhsCasted.search(clazzType);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
public override bool replace(Statement thiz, Statement that)
|
||||
{
|
||||
/* We cannot directly replace ourselves */
|
||||
if(this == thiz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* Is the left-hand side `Expression` to be replaced? */
|
||||
else if(thiz == lhs)
|
||||
{
|
||||
lhs = cast(Expression)that;
|
||||
return true;
|
||||
}
|
||||
/* Is the right-hand side `Expression` to be replaced? */
|
||||
else if(thiz == rhs)
|
||||
{
|
||||
rhs = cast(Expression)that;
|
||||
return true;
|
||||
}
|
||||
/* If not direct match, then recurse and replace on left-hand side `Expression` (if possible) */
|
||||
else if(cast(MStatementReplaceable)lhs)
|
||||
{
|
||||
MStatementReplaceable lhsCasted = cast(MStatementReplaceable)lhs;
|
||||
return lhsCasted.replace(thiz, that);
|
||||
}
|
||||
/* If not direct match, then recurse and replace on right-hand side `Expression` (if possible) */
|
||||
else if(cast(MStatementReplaceable)rhs)
|
||||
{
|
||||
MStatementReplaceable rhsCasted = cast(MStatementReplaceable)rhs;
|
||||
return rhsCasted.replace(thiz, that);
|
||||
}
|
||||
/* If not direct match and not replaceable */
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum IntegerLiteralEncoding
|
||||
|
@ -93,7 +161,7 @@ public enum IntegerLiteralEncoding
|
|||
UNSIGNED_LONG
|
||||
}
|
||||
|
||||
public final class IntegerLiteral : NumberLiteral
|
||||
public class IntegerLiteral : NumberLiteral
|
||||
{
|
||||
private IntegerLiteralEncoding encoding;
|
||||
|
||||
|
@ -143,6 +211,11 @@ public abstract class NumberLiteral : Expression
|
|||
{
|
||||
return numberLiteral;
|
||||
}
|
||||
|
||||
public final void setNumber(string numberLiteral)
|
||||
{
|
||||
this.numberLiteral = numberLiteral;
|
||||
}
|
||||
}
|
||||
|
||||
public class Expression : Statement
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
module tlang.compiler.symbols.mcro;
|
||||
|
||||
import tlang.compiler.symbols.data;
|
||||
|
||||
public class Macro : Statement
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public interface MTypeRewritable
|
||||
{
|
||||
public string getType();
|
||||
public void setType(string type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Anything which implements this has the ability
|
||||
* to search for objects of the provided type,
|
||||
* and return a list of them
|
||||
*/
|
||||
public interface MStatementSearchable
|
||||
{
|
||||
/**
|
||||
* Searches for all objects of the given type
|
||||
* and returns an array of them. Only if the given
|
||||
* type is equal to or sub-of `Statement`
|
||||
*
|
||||
* Params:
|
||||
* clazzType = the type to search for
|
||||
* Returns: an array of `Statement` (a `Statement[]`)
|
||||
*/
|
||||
public Statement[] search(TypeInfo_Class clazzType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Anything which implements this has the ability
|
||||
* to, given an object `x`, return a `ref x` to it
|
||||
* hence allowing us to replace it
|
||||
*/
|
||||
public interface MStatementReplaceable
|
||||
{
|
||||
/**
|
||||
* Replace a given `Statement` with another `Statement`
|
||||
*
|
||||
* Params:
|
||||
* thiz = the `Statement` to replace
|
||||
* that = the `Statement` to insert in-place
|
||||
* Returns: `true` if the replacement succeeded, `false` otherwise
|
||||
*/
|
||||
public bool replace(Statement thiz, Statement that);
|
||||
}
|
||||
|
||||
/**
|
||||
* Anything which implements this can make a full
|
||||
* deep clone of itself
|
||||
*/
|
||||
public interface MCloneable
|
||||
{
|
||||
/**
|
||||
* Returns a `Statement` which is a clone of this one
|
||||
* itself
|
||||
*
|
||||
* Returns: the cloned `Statement`
|
||||
*/
|
||||
public Statement clone();
|
||||
}
|
|
@ -14,6 +14,8 @@ import tlang.compiler.typecheck.dependency.core;
|
|||
import tlang.compiler.codegen.instruction;
|
||||
import std.container.slist;
|
||||
import std.algorithm : reverse;
|
||||
import tlang.compiler.typecheck.meta;
|
||||
import tlang.compiler.configuration;
|
||||
|
||||
/**
|
||||
* The Parser only makes sure syntax
|
||||
|
@ -24,23 +26,58 @@ import std.algorithm : reverse;
|
|||
*/
|
||||
public final class TypeChecker
|
||||
{
|
||||
/**
|
||||
* The compiler configuration
|
||||
*/
|
||||
private CompilerConfiguration config;
|
||||
|
||||
|
||||
|
||||
private Module modulle;
|
||||
|
||||
/* The name resolver */
|
||||
private Resolver resolver;
|
||||
|
||||
/**
|
||||
* The meta-programming processor
|
||||
*/
|
||||
private MetaProcessor meta;
|
||||
|
||||
public Module getModule()
|
||||
{
|
||||
return modulle;
|
||||
}
|
||||
|
||||
this(Module modulle)
|
||||
/**
|
||||
* Constructs a new `TypeChecker` based on the provided `Module`
|
||||
* of which to typecheck its members and using the default
|
||||
* compiler configuration
|
||||
*
|
||||
* Params:
|
||||
* modulle = the `Module` to check
|
||||
* config = the `CompilerConfiguration` (default if not specified)
|
||||
*/
|
||||
this(Module modulle, CompilerConfiguration config = CompilerConfiguration.defaultConfig())
|
||||
{
|
||||
this.modulle = modulle;
|
||||
resolver = new Resolver(this);
|
||||
this.config = config;
|
||||
|
||||
this.resolver = new Resolver(this);
|
||||
this.meta = new MetaProcessor(this, true);
|
||||
|
||||
/* TODO: Module check?!?!? */
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the compiler configuration
|
||||
*
|
||||
* Returns: the `CompilerConfguration`
|
||||
*/
|
||||
public CompilerConfiguration getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* I guess this should be called rather
|
||||
* when processing assignments but I also
|
||||
|
@ -2106,6 +2143,9 @@ public final class TypeChecker
|
|||
*/
|
||||
public void beginCheck()
|
||||
{
|
||||
/* Run the meta-processor on the AST tree (starting from the Module) */
|
||||
meta.process(modulle);
|
||||
|
||||
/* Process all pseudo entities of the given module */
|
||||
processPseudoEntities(modulle);
|
||||
|
||||
|
|
|
@ -0,0 +1,413 @@
|
|||
module tlang.compiler.typecheck.meta;
|
||||
|
||||
import tlang.compiler.symbols.data : Statement, TypedEntity, Function, FunctionCall, IdentExpression;
|
||||
import tlang.compiler.symbols.expressions : Expression, IntegerLiteral, IntegerLiteralEncoding;
|
||||
import tlang.compiler.symbols.typing.core;
|
||||
import tlang.compiler.symbols.containers : Container;
|
||||
import tlang.compiler.symbols.mcro;
|
||||
import tlang.compiler.typecheck.core;
|
||||
import gogga;
|
||||
import std.conv : to;
|
||||
import tlang.compiler.configuration;
|
||||
|
||||
/**
|
||||
* The `MetaProcessor` is used to do a pass over a `Container`
|
||||
* to process any macro and macro-like entities
|
||||
*/
|
||||
public class MetaProcessor
|
||||
{
|
||||
private TypeChecker tc;
|
||||
private bool isMetaEnabled;
|
||||
private CompilerConfiguration compilerConfig;
|
||||
|
||||
/**
|
||||
* Constructs a new `MetaProcessor` for the purposes of
|
||||
* modifying the AST tree before the typechecker traverses
|
||||
* it
|
||||
*
|
||||
* Params:
|
||||
* tc = the `TypeChecker` instance to process
|
||||
* isMetaEnabled = `true` if to perform meta processing, otherwise `false`
|
||||
*/
|
||||
this(TypeChecker tc, bool isMetaEnabled)
|
||||
{
|
||||
this.tc = tc;
|
||||
this.isMetaEnabled = isMetaEnabled;
|
||||
this.compilerConfig = tc.getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the provided `Container` and searches for any `Macro`-like
|
||||
* parse-nodes to process
|
||||
*/
|
||||
public void process(Container container)
|
||||
{
|
||||
/* Only apply meta-processing if enabled */
|
||||
if(!isMetaEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get all statements */
|
||||
Statement[] stmts = container.getStatements();
|
||||
|
||||
foreach(Statement curStmt; stmts)
|
||||
{
|
||||
gprintln("MetaProcessor: Examining AST node '"~curStmt.toString()~"'...");
|
||||
|
||||
// Perform replacement of all type alises to concrete types, such as `size_t`
|
||||
doTypeAlias(container, curStmt);
|
||||
|
||||
/**
|
||||
* Search for any `sizeof(<ident_type>)` expressions
|
||||
* and replace them with a `NumberLiteral`
|
||||
*/
|
||||
if(cast(MStatementSearchable)curStmt && cast(MStatementReplaceable)curStmt)
|
||||
{
|
||||
MStatementSearchable searchableStmt = cast(MStatementSearchable)curStmt;
|
||||
Statement[] foundStmts = searchableStmt.search(FunctionCall.classinfo);
|
||||
gprintln("Nah fr");
|
||||
|
||||
foreach(Statement curFoundStmt; foundStmts)
|
||||
{
|
||||
FunctionCall curFuncCall = cast(FunctionCall)curFoundStmt;
|
||||
|
||||
if(curFuncCall.getName() == "sizeof")
|
||||
{
|
||||
gprintln("Elo");
|
||||
Expression[] arguments = curFuncCall.getCallArguments();
|
||||
if(arguments.length == 1)
|
||||
{
|
||||
IdentExpression potentialIdentExp = cast(IdentExpression)arguments[0];
|
||||
if(potentialIdentExp)
|
||||
{
|
||||
string typeName = potentialIdentExp.getName();
|
||||
IntegerLiteral replacementStmt = sizeOf_Literalize(typeName);
|
||||
gprintln("sizeof: Replace '"~curFoundStmt.toString()~"' with '"~replacementStmt.toString()~"'");
|
||||
|
||||
/* Traverse down from the `Container` we are process()'ing and apply the replacement */
|
||||
MStatementReplaceable containerRepl = cast(MStatementReplaceable)container;
|
||||
containerRepl.replace(curFoundStmt, replacementStmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Throw an exception here that an ident_type should be present as the argument
|
||||
gprintln("The argument to `sizeof` should be an ident", DebugType.ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Throw an exception here as only 1 argument is allowed
|
||||
gprintln("To use the `sizeof` macro you require a single argument to be passed to it", DebugType.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current statement is a Container then recurse
|
||||
*
|
||||
* This will help us do the following:
|
||||
*
|
||||
* 1. Type re-writing of
|
||||
* a. Functions (Parameters and Body as both make up its Statement[])
|
||||
*/
|
||||
if(cast(Container)curStmt)
|
||||
{
|
||||
process(cast(Container)curStmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-writes the types for things such as `size_t`, `ssize_t` and so forth
|
||||
*
|
||||
* Params:
|
||||
* statement = the `MTypeRewritable` to apply re-writing to
|
||||
*/
|
||||
private void typeRewrite(MTypeRewritable statement)
|
||||
{
|
||||
/* Applies re-write to Variable's declared type and Function's return type */
|
||||
string type = statement.getType();
|
||||
|
||||
/* Only re-write if type alias */
|
||||
if(isTypeAlias(type))
|
||||
{
|
||||
/* Get the concrete type of `type` */
|
||||
string concreteType = getConcreteType(type);
|
||||
|
||||
/* Rewrite the type */
|
||||
statement.setType(concreteType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the replacement of type alieses such as `size_t`, `ssize_t`
|
||||
* and so forth with their concrete type
|
||||
*
|
||||
* Params:
|
||||
* container = the current `Container` being processsed
|
||||
* curStmt = the current `Statement` to consider
|
||||
*/
|
||||
private void doTypeAlias(Container container, Statement curStmt)
|
||||
{
|
||||
/**
|
||||
* Apply type-rewriting to any `MTypeRewritable` AST node
|
||||
* (a.k.a. a node which contains a type and can have it set)
|
||||
*
|
||||
* NOTE: This is just for the "type" fields in AST nodes,
|
||||
* we should have some full recursive re-writer.
|
||||
*
|
||||
* An example of why is for supporting something like:
|
||||
*
|
||||
* `sizeof(size_t)` <- currently is not supported by this
|
||||
*/
|
||||
if(cast(MTypeRewritable)curStmt)
|
||||
{
|
||||
typeRewrite(cast(MTypeRewritable)curStmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Here we will also search for any `IdentExpression`
|
||||
* which contains `size_t`, `ssize_t` etc. and replace
|
||||
* them
|
||||
*/
|
||||
if(cast(MStatementSearchable)curStmt && cast(MStatementReplaceable)curStmt)
|
||||
{
|
||||
MStatementSearchable searchableStmt = cast(MStatementSearchable)curStmt;
|
||||
IdentExpression[] foundStmts = cast(IdentExpression[])searchableStmt.search(IdentExpression.classinfo);
|
||||
|
||||
// TODO: Implement me
|
||||
// gprintln("IdentExpressions found: "~to!(string)(foundStmts));
|
||||
|
||||
/**
|
||||
* Loop through all `IdentExpression`s and find any
|
||||
* occurence of `size_t`/`ssize_t` and replace those
|
||||
* with the concrete type
|
||||
*/
|
||||
foreach(IdentExpression identExp; foundStmts)
|
||||
{
|
||||
string identName = identExp.getName();
|
||||
|
||||
/* Determine if this is a type alias? */
|
||||
if(isTypeAlias(identName))
|
||||
{
|
||||
// Determine the concrete type
|
||||
string concereteType = getConcreteType(identName);
|
||||
gprintln("Found type alias '"~identName~"' which concretely is '"~concereteType~"'");
|
||||
|
||||
// Replace with concrete type
|
||||
container.replace(identExp, new IdentExpression(concereteType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IntegerLiteral sizeOf_Literalize(string typeName)
|
||||
{
|
||||
IntegerLiteral literal = new IntegerLiteral("TODO_LITERAL_GOES_HERESIZEOF_REPLACEMENT", IntegerLiteralEncoding.UNSIGNED_INTEGER);
|
||||
|
||||
// TODO: Via typechecker determine size with a lookup
|
||||
Type type = tc.getType(tc.getModule(), typeName);
|
||||
|
||||
/* Calculated type size */
|
||||
ulong typeSize = 0;
|
||||
|
||||
/**
|
||||
* Calculate stack array size
|
||||
*
|
||||
* Algo: `<componentType>.size * stackArraySize`
|
||||
*/
|
||||
if(cast(StackArray)type)
|
||||
{
|
||||
StackArray stackArrayType = cast(StackArray)type;
|
||||
ulong arrayLength = stackArrayType.getAllocatedSize();
|
||||
Type componentType = stackArrayType.getComponentType();
|
||||
ulong componentTypeSize = 0;
|
||||
|
||||
// FIXME: Later, when the Dependency Genrator supports more advanced component types,
|
||||
// ... we will need to support this - for now assume that `componentType` is primitive
|
||||
if(cast(Number)componentType)
|
||||
{
|
||||
Number numberType = cast(Number)componentType;
|
||||
componentTypeSize = numberType.getSize();
|
||||
}
|
||||
|
||||
typeSize = componentTypeSize*arrayLength;
|
||||
}
|
||||
/**
|
||||
* Calculate the size of `Number`-based types
|
||||
*/
|
||||
else if(cast(Number)type)
|
||||
{
|
||||
Number numberType = cast(Number)type;
|
||||
typeSize = numberType.getSize();
|
||||
}
|
||||
|
||||
// TODO: We may eed toupdate Type so have bitwidth or only do this
|
||||
// for basic types - in which case I guess we should throw an exception
|
||||
// here.
|
||||
// ulong typeSize =
|
||||
|
||||
|
||||
|
||||
/* Update the `Sizeof` kind-of-`IntegerLiteral` with the new size */
|
||||
literal.setNumber(to!(string)(typeSize));
|
||||
|
||||
return literal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the type alias into its concrete type.
|
||||
*
|
||||
* This method incorporates defensive programming in
|
||||
* that it will only apply the transformation IF
|
||||
* the provided type alias is infact a type alias,
|
||||
* otherwise it performs an identity transformation
|
||||
* and returns the "alias" untouched.
|
||||
*
|
||||
* Params:
|
||||
* typeAlias = the potential type alias
|
||||
* Returns: the concrete type, or `typeAlias` if
|
||||
* not an alias
|
||||
*/
|
||||
private string getConcreteType(string typeAlias)
|
||||
{
|
||||
/* Check if this is a system type alias? If so, transform */
|
||||
if(isSystemType(typeAlias))
|
||||
{
|
||||
return getSystemType(typeAlias);
|
||||
}
|
||||
// TODO: Add user-defined type alias support here
|
||||
/* Else, return the "alias" untouched */
|
||||
else
|
||||
{
|
||||
return typeAlias;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given type is a type alias.
|
||||
*
|
||||
* Params:
|
||||
* typeAlias = the type to check
|
||||
* Returns: `true` if it is an alias, `false` otherwise
|
||||
*/
|
||||
private bool isTypeAlias(string typeAlias)
|
||||
{
|
||||
/* If this a system type alias? */
|
||||
if(isSystemType(typeAlias))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// TODO: Support for user-defined type aliases
|
||||
/* Otherwise, not a type alias */
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given type is a system type alias
|
||||
*
|
||||
* Params:
|
||||
* typeAlias = the type to check
|
||||
* Returns: `true` if system type alias, `false` otherwise
|
||||
*/
|
||||
private bool isSystemType(string typeAlias)
|
||||
{
|
||||
/* `size_t`/`ssize_t` system type aliases */
|
||||
if(typeAlias == "size_t" || typeAlias == "ssize_t")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/* Else, not a system type alias */
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a type alias (think `size_t`/`ssize_t` for example) this will
|
||||
* look up in the compiler's configuration what that size should be
|
||||
* resolved to
|
||||
*
|
||||
* Params:
|
||||
* typeAlias = the system type alias to lookup
|
||||
* Returns: the concrete type
|
||||
*/
|
||||
private string getSystemType(string typeAlias)
|
||||
{
|
||||
/* Determine machine's width */
|
||||
ulong maxWidth = compilerConfig.getConfig("types:max_width").getNumber();
|
||||
|
||||
string maxType;
|
||||
|
||||
if(maxWidth == 1)
|
||||
{
|
||||
if(typeAlias == "size_t")
|
||||
{
|
||||
return "ubyte";
|
||||
}
|
||||
else if(typeAlias == "ssize_t")
|
||||
{
|
||||
return "byte";
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else if(maxWidth == 2)
|
||||
{
|
||||
if(typeAlias == "size_t")
|
||||
{
|
||||
return "ushort";
|
||||
}
|
||||
else if(typeAlias == "ssize_t")
|
||||
{
|
||||
return "short";
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else if(maxWidth == 4)
|
||||
{
|
||||
if(typeAlias == "size_t")
|
||||
{
|
||||
return "uint";
|
||||
}
|
||||
else if(typeAlias == "ssize_t")
|
||||
{
|
||||
return "int";
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else if(maxWidth == 8)
|
||||
{
|
||||
if(typeAlias == "size_t")
|
||||
{
|
||||
return "ulong";
|
||||
}
|
||||
else if(typeAlias == "ssize_t")
|
||||
{
|
||||
return "long";
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
module simple_meta_replace;
|
||||
|
||||
void function()
|
||||
{
|
||||
discard repr;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
module meta_sizeof;
|
||||
|
||||
size_t myVar1 = sizeof(uint);
|
||||
size_t myVar2 = sizeof(ubyte);
|
||||
size_t myVar3 = sizeof(ushort)+1;
|
||||
|
||||
myVar3 = sizeof(ulong)+sizeof(size_t);
|
|
@ -0,0 +1,3 @@
|
|||
module simple_template_type_def;
|
||||
|
||||
generic T;
|
|
@ -0,0 +1,8 @@
|
|||
module meta_types;
|
||||
|
||||
size_t myVar = 1;
|
||||
|
||||
size_t function(size_t param1)
|
||||
{
|
||||
return 1UL+myVar;
|
||||
}
|
Loading…
Reference in New Issue