- Added new type `VariableParameter` for function parameters

Parser

- Generate instances of `VariableParameter` instead of just `Variable` (direct) for function parameters
- Set the Container of the VariableParameter(s) of a function definition to that of the Function (definition)

TypeCheck

- Updated type to `VariableParameter` (just to be more specific and clear)

Dependency

- Added branch to pool VariableParameter but NOT add them as dnode's (that would cause code gen to emit declarations for parameters - which is something we do not want). Set as visited, pool for lookup and set Context.

DGen

- Added variable parameter symbol mapping to `generateSignature()` for function signatures

Variables (special DNode type)

- Added note, do we need these?

Test cases

- Updated test case `simple_function_decls.t` to test parameter variable usage (assignment and expression usage)
This commit is contained in:
Tristan B. Velloza Kildaire 2022-12-16 18:04:57 +02:00
parent 2a12c310a6
commit 8972a277f3
7 changed files with 81 additions and 18 deletions

View File

@ -14,7 +14,7 @@ import std.string : wrap;
import std.process : spawnProcess, Pid, ProcessException, wait;
import compiler.typecheck.dependency.core : Context, FunctionData, DNode;
import compiler.codegen.mapper : SymbolMapper;
import compiler.symbols.data : SymbolType, Variable, Function;
import compiler.symbols.data : SymbolType, Variable, Function, VariableParameter;
import compiler.symbols.check : getCharacter;
import misc.utils : Stack;
@ -287,13 +287,21 @@ public final class DCodeEmitter : CodeEmitter
// Generate parameter list
if(func.hasParams())
{
Variable[] parameters = func.getParams();
VariableParameter[] parameters = func.getParams();
string parameterString;
for(ulong parIdx = 0; parIdx < parameters.length; parIdx++)
{
Variable currentParameter = parameters[parIdx];
parameterString~=currentParameter.getType()~" "~currentParameter.getName();
// Generate the symbol-mapped names for the parameters
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(func, currentParameter.getName()); //TODO: Remove `auto`
string typedEntityVariableName = typeChecker.getResolver().generateName(func, typedEntityVariable);
string renamedSymbol = SymbolMapper.symbolLookup(func, typedEntityVariableName);
// Generate <type> <parameter-name (symbol mapped)>
parameterString~=currentParameter.getType()~" "~renamedSymbol;
if(parIdx != (parameters.length-1))
{

View File

@ -718,7 +718,7 @@ public final class Parser
private struct funcDefPair
{
Statement[] bodyStatements;
Variable[] args;
VariableParameter[] params;
}
private funcDefPair parseFuncDef()
@ -726,7 +726,7 @@ public final class Parser
gprintln("parseFuncDef(): Enter", DebugType.WARNING);
Statement[] statements;
Variable[] argumentList;
VariableParameter[] parameterList;
funcDefPair bruh;
@ -760,7 +760,7 @@ public final class Parser
/* Add the local variable (parameter variable) */
argumentList ~= new Variable(type, identifier);
parameterList ~= new VariableParameter(type, identifier);
moreArgs = false;
@ -807,7 +807,7 @@ public final class Parser
gprintln("parseFuncDef(): Leave", DebugType.WARNING);
bruh.bodyStatements = statements;
bruh.args = argumentList;
bruh.params = parameterList;
return bruh;
}
@ -1146,12 +1146,15 @@ public final class Parser
{
funcDefPair pair = parseFuncDef();
generated = new Function(identifier, type, pair.bodyStatements, pair.args);
generated = new Function(identifier, type, pair.bodyStatements, pair.params);
import std.stdio;
writeln(to!(string)((cast(Function)generated).getVariables()));
// Parent the parameters of the function to the Function
parentToContainer(cast(Container)generated, cast(Statement[])pair.params);
// Parent the statements that make up the function to the Function
parentToContainer(cast(Container)generated, pair.bodyStatements);
}
/* Check for semi-colon (var dec) */

View File

@ -231,24 +231,54 @@ public class ArgumentList
}
/**
* VariableParameter
*
* Represents a kindof-Variable which is used to indicate
* it is a function's parameter - to differentiate between
* those and other variables like local/global definitions
* and so on
*
* These are only to be used in the `Function` class (below)
*/
public final class VariableParameter : Variable
{
this(string type, string identifier)
{
super(type, identifier);
}
}
/* TODO: Don't make this a Container, or maybe (make sure I don't rely on COntainer casting for other shit
* though, also the recent changes) */
public class Function : TypedEntity, Container
{
private Variable[] params;
private VariableParameter[] params;
private Statement[] bodyStatements;
this(string name, string returnType, Statement[] bodyStatements, Variable[] args)
this(string name, string returnType, Statement[] bodyStatements, VariableParameter[] params)
{
super(name, returnType);
this.bodyStatements = bodyStatements;
this.params = args;
// Add the parameters first THEN the function's body statements
// because they must be available before other statements
// which may reference them, Secondly they must be added (the VariableParameter(s))
// such that they are lookup-able.
addStatements(cast(Statement[])params);
// Add the funciton's body
addStatements(bodyStatements);
// Save a seperate copy of the parameters (to seperate them from the
// other body stetements)
this.params = params;
/* Weighted as 1 */
weight = 1;
}
public Variable[] getParams()
public VariableParameter[] getParams()
{
return params;
}

View File

@ -632,7 +632,7 @@ public final class TypeChecker
/* TODO: Look up func def to know when popping stops (types-based delimiting) */
Function func = cast(Function)resolver.resolveBest(modulle, funcCall.getName());
assert(func);
Variable[] paremeters = func.getParams();
VariableParameter[] paremeters = func.getParams();
/* TODO: Pass in FUnction, so we get function's body for calling too */

View File

@ -736,7 +736,6 @@ public class DNodeGenerator
varExp.setContext(context);
gprintln("Kont: "~to!(string)(context));
if(namedEntity)
{
@ -1179,10 +1178,27 @@ public class DNodeGenerator
continue;
}
/**
* Variable paremeters (for functions)
*/
if(cast(VariableParameter)entity)
{
VariableParameter varParamDec = cast(VariableParameter)entity;
// Set context
entity.setContext(context);
// Pool and mark as visited
// NOTE: I guess for now use VariableDNode as that is what is used in expressionPass
// with the poolT! constrcutor, doing otherwise causes a cast failure and hence
// null: /git/tlang/tlang/issues/52#issuecomment-325
DNode dnode = poolT!(VariableNode, Variable)(varParamDec);
dnode.markVisited();
}
/**
* Variable declarations
*/
if(cast(Variable)entity)
else if(cast(Variable)entity)
{
/* Get the Variable and information */
Variable variable = cast(Variable)entity;

View File

@ -9,6 +9,8 @@ import compiler.symbols.data;
* and struct-level
*/
//TODO: See how needed these REALLY are (see issue #55)
public class VariableNode : DNode
{
private Variable variable;

View File

@ -3,12 +3,16 @@ module simple_function_decls;
int j = 21;
int k = 22;
int apple(int j, int arg2)
int apple(int arg1, int arg2)
{
int h = 69;
arg1=1+arg1;
k=1;
}
int banana(int j)
int banana(int arg1)
{
int h = 64;