🧠 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 stagesresearch/gmalloc
parent
c65c41eed2
commit
39508a5907
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.
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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