Skip to content
This repository has been archived by the owner on Apr 25, 2021. It is now read-only.

Commit

Permalink
Merge pull request #21 from AjaniBilby/dev
Browse files Browse the repository at this point in the history
+Static/Dynamic length arrays; ~updated casting
  • Loading branch information
AjaniBilby authored Jul 29, 2020
2 parents 42a7749 + 8dd2736 commit 7236129
Show file tree
Hide file tree
Showing 18 changed files with 461 additions and 288 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"editor.insertSpaces": false,
"files.eol": "\n",
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"files.associations": {
"*.qp": "qupa",
"cstdio": "cpp"
}
}
21 changes: 21 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Change Log

## Unreleased

### Added

+ Statically defined length arrays
+ Dynamically defined length arrays
+ Primative compile time resolved function ``sizeof()``
+ Primative function ``static_cast`` - allows primative type conversion, and pointer conversion
+ Primative memory allocation functions ``malloc()``/``free()``

### Fixes

+ Incorrect datatype error logging
+ Fixed template datatype parsing

### Changes

+ Templates usable for datatype access
+ Bitcasting replaced with ``static_cast``
215 changes: 108 additions & 107 deletions compiler/component/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,17 @@ class Execution {






/**
* Get a register
* @param {*} ast
* @param {Boolean} read
*/
getVar(ast, read = true) {
// Link dynamic access arguments
for (let access of ast.tokens[2]) {
if (access[0] == "[]") {
for (let i in access[1]) {
let res = this.compile_expr(access[1][i], null, true);
if (res === null) {
return {
error: true,
msg: `Error: Unexpected dynamic access opperand type ${arg.type}`,
ref: arg.ref
};
}

access[1][i] = res;
}
}
}
ast = this.resolveAccess(ast);

let res = this.scope.getVar(ast, read);

Expand All @@ -88,6 +81,49 @@ class Execution {
return res;
}

/**
* Load a variable ready for access
* @param {BNF_Node} ast
*/
compile_loadVariable(ast) {
let frag = new LLVM.Fragment();

let load = this.getVar(ast, true);
if (load.error) {
this.getFile().throw(load.msg, load.ref.start, load.ref.end);
return null;
}
frag.merge(load.preamble);

let count = ast.tokens[0]+1;
let cache = load.register.deref(this.scope, true, count);
if (!cache.register) {
let name = Flattern.VariableStr(ast);
this.getFile().throw(
`Error: Cannot dereference ${Flattern.DuplicateChar(count, "$")}${name}`,
ast.ref.start, ast.ref.end
);
return null;
}
frag.merge(cache.preamble);

return {
instruction: new LLVM.Argument(
new LLVM.Type(cache.register.type.represent, cache.register.pointer),
new LLVM.Name(cache.register.id, null),
null,
load.register.name
),
preamble: frag,
epilog: new LLVM.Fragment(),
type: new TypeRef(cache.register.pointer, cache.register.type),
register: cache.register
};
}






/**
Expand All @@ -111,6 +147,9 @@ class Execution {
return null;
}

// Update pointer size
type.pointer = arg.tokens[0];

template.push(type);
break;
case "constant":
Expand All @@ -127,6 +166,7 @@ class Execution {

return template;
}

/**
*
* @param {BNF_Node} node
Expand All @@ -143,6 +183,35 @@ class Execution {
);
}

/**
* Resolves any dynamic access for the variable
* ALTERS original AST
* @param {*} ast
*/
resolveAccess (ast) {
for (let access of ast.tokens[2]) {
if (access[0] == "[]") {
for (let i in access[1]) {
let res = this.compile_expr(access[1][i], null, true);
if (res === null) {
return {
error: true,
msg: `Error: Unexpected dynamic access opperand type ${arg.type}`,
ref: arg.ref
};
}

access[1][i] = res;
}
}
}

return ast;
}






/**
Expand Down Expand Up @@ -172,46 +241,6 @@ class Execution {
};
}

/**
* Load a variable
* @param {BNF_Node} ast
*/
compile_loadVariable(ast) {
let frag = new LLVM.Fragment();

let load = this.getVar(ast, true);
if (load.error) {
this.getFile().throw(load.msg, load.ref.start, load.ref.end);
return null;
}
frag.merge(load.preamble);

let count = ast.tokens[0]+1;
let cache = load.register.deref(this.scope, true, count);
if (!cache.register) {
let name = Flattern.VariableStr(ast);
this.getFile().throw(
`Error: Cannot dereference ${Flattern.DuplicateChar(count, "$")}${name}`,
ast.ref.start, ast.ref.end
);
return null;
}
frag.merge(cache.preamble);

return {
instruction: new LLVM.Argument(
new LLVM.Type(cache.register.type.represent, cache.register.pointer),
new LLVM.Name(cache.register.id, null),
null,
load.register.name
),
preamble: frag,
epilog: new LLVM.Fragment(),
type: new TypeRef(cache.register.pointer, cache.register.type),
register: cache.register
};
}

/**
* Generates the LLVM for a call
* Used in other compile functions
Expand Down Expand Up @@ -244,7 +273,7 @@ class Execution {
regs.push(load.register);
signature.push(load.type);
} else {
let expr = this.compile_expr(arg, null, true, ['call']);
let expr = this.compile_expr(arg, null, true, true);
if (expr === null) {
return null;
}
Expand All @@ -264,47 +293,11 @@ class Execution {
let file = this.getFile();
for (let access of ast.tokens[0].tokens[2]) {
if (access.tokens[0] == "[]") {
let out = [];
for (let inner of access.tokens[1].tokens) {
if (inner.type != "variable") {
file.throw (
`Error: Non-variable accessors are not allowed at this time`,
inner.ref.start, inner.ref.end
);
return null;
}

let target = this.getVar(inner, true);
if (target.error !== true) {
file.throw(
`Error: Cannot processed variables withiin [] for function access`,
inner.ref.start, inner.ref.end
);
return null;
}

let forward = Flattern.VariableList(inner);
if (forward[0][0] != 0) {
file.throw(
`Error: Cannot dereference function call ${Flattern.VariableStr(inner)}`,
inner.ref.start, inner.ref.end
);
return null;
}

target = file.getType(forward);

if (!target) {
file.throw(
`Error: Unknown variable ${Flattern.VariableStr(inner)}`,
inner.ref.start, inner.ref.end
);
return null;
}
out.push(target);
}

accesses.push(out);
file.throw (
`Error: Class base function execution is currently unsupported`,
inner.ref.start, inner.ref.end
);
return null;
} else {
accesses.push([access.tokens[0], access.tokens[1].tokens]);
}
Expand Down Expand Up @@ -416,6 +409,7 @@ class Execution {

return frag;
}

/**
* Generates the LLVM for assigning a variable
* @param {BNF_Node} ast
Expand Down Expand Up @@ -473,6 +467,7 @@ class Execution {
frag.merge(expr.epilog);
return frag;
}

/**
* Generates the LLVM for the combined action of define + assign
* @param {BNF_Node} ast
Expand Down Expand Up @@ -732,21 +727,19 @@ class Execution {
* @param {Array[Number, TypeDef]} expects
* @param {Boolean} simple Simplifies the result to a single register when possible
*/
compile_expr (ast, expects = null, simple = false, block = []) {
if (block.includes(ast.type)) {
this.getFile().throw(
`Error: Cannot call ${ast.type} within a nested expression`,
ast.ref.start, ast.ref.end
);
return null;
}

compile_expr (ast, expects = null, simple = false, block = false) {
let recursiveFail = false;
let res = null;
switch (ast.type) {
case "constant":
res = this.compile_constant(ast);
break;
case "call":
if (block) {
recursiveFail = true;
break;
}

res = this.compile_call(ast);
break;
case "variable":
Expand All @@ -756,6 +749,14 @@ class Execution {
throw new Error(`Unexpected expression type ${ast.type}`);
}

if (recursiveFail) {
this.getFile().throw(
`Error: Recursive expression are not allowed at this stage`,
ast.ref.start, ast.ref.end
);
return null;
}

if (res === null) {
return null;
}
Expand Down
Loading

0 comments on commit 7236129

Please sign in to comment.