Skip to content

Commit

Permalink
fix: memory layout issue (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
menduz authored Dec 24, 2019
1 parent f2fdf6a commit a4d2296
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 53 deletions.
31 changes: 31 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,37 @@
- for in sugar syntax
- robust type alias use cases and test suites

```lys
// this should yield an error
match x {
case 1 -> ???
case 1 -> ???
case 1 -> ???
case 1 -> ???
}
```

```lys
// doesnt work
match x {
else char -> ...
}
```

```lys
// assignment as firts code block stmt dowsnt work
match parse(rule, ruleName, parser, level + 1) {
case is Nil -> break
case ast is AST -> {
ret = match ret {
case is Nil -> ast
else -> AstCons(ret, ast)
}
continue
}
}
```

every declaration with the same name of different impl must have the same visibility

exhaustive test of implicit coercion
Expand Down
122 changes: 122 additions & 0 deletions examples/tests/struct-memory-layout.spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Test

Smoke tests of memory layout

#### main.lys

```lys
import support::test
import system::charset::utf8
enum TokenType {
EndOfFile
Identifier
Unknown
NewLine
Whitespace
StringLiteral
NumberLiteral
ParenthesesOpen
ParenthesesClose
MacroDecoration
VectorOpen
VectorClose
Operator
LineComment
MultiLineComment
CurlyBracesOpen
CurlyBracesClose
Comma
}
struct Token(tokenType: TokenType, start: u32, end: u32)
enum ParserRule {
Terminal(tokenType: TokenType)
StrictTerminal(tokenType: TokenType, value: string)
NonTerminal(name: string)
Or(lhs: ParserRule, rhs: ParserRule)
OneOrMore(rule: ParserRule)
ZeroOrMore(rule: ParserRule)
Cons(head: ParserRule, tail: ParserRule)
Cut(head: ParserRule, tail: ParserRule)
Optional(rule: ParserRule)
Fail(message: string)
LookAhead(rule: ParserRule)
NegativeLookAhead(rule: ParserRule)
Discard(rule: ParserRule)
Push(name: string, rule: ParserRule)
PushIfManyChildren(name: string, rule: ParserRule)
}
enum AstNode {
Rule0
Leaf(token: Token, value: string)
Node(name: string, child: AstNode)
Numbers(a: u8, b: u16, c: u32, d: u64)
SyntaxError(token: Token, message: string)
UnexpectedToken(token: Token, value: string)
AstCons(head: AstNode, tail: AstNode)
}
#[export]
fun test(): void = {
START("test basics")
var t = 0x0
t = Numbers.^property$0_offset
mustEqual(t, 0x0, "Numbers.property0 must start at 0")
t = Numbers.^property$1_offset
mustEqual(t, 0x1, "Numbers.property1 must start at 1")
t = Numbers.^property$2_offset
mustEqual(t, 0x3, "Numbers.property2 must start at 3")
t = Numbers.^property$3_offset
mustEqual(t, 0x7, "Numbers.property3 must start at 7")
t = Numbers.^allocationSize
mustEqual(t, 0xF, "Numbers.allocationSize must be 15")
t = Node.^property$0_offset
mustEqual(t, 0x0, "Node.property0 must start at 0")
t = Node.^property$1_offset
mustEqual(t, 0x8, "Node.property1 must start at 8")
t = Node.^allocationSize
mustEqual(t, 0x10, "Node.allocationSize must be 16")
t = Leaf.^property$0_offset
mustEqual(t, 0x0, "Leaf.property0 must start at 0")
t = Leaf.^property$1_offset
mustEqual(t, 0x8, "Leaf.property1 must start at 8")
t = Leaf.^allocationSize
mustEqual(t, 0x10, "Leaf.allocationSize must be 16")
t = SyntaxError.^property$0_offset
mustEqual(t, 0x0, "SyntaxError.property0 must start at 0")
t = SyntaxError.^property$1_offset
mustEqual(t, 0x8, "SyntaxError.property1 must start at 8")
t = SyntaxError.^allocationSize
mustEqual(t, 0x10, "SyntaxError.allocationSize must be 16")
t = AstCons.^property$0_offset
mustEqual(t, 0x0, "AstCons.property0 must start at 0")
t = AstCons.^property$1_offset
mustEqual(t, 0x8, "AstCons.property1 must start at 8")
t = AstCons.^allocationSize
mustEqual(t, 0x10, "AstCons.allocationSize must be 16")
t = Token.^property$0_offset
mustEqual(t, 0x0, "Token.property0 must start at 0")
t = Token.^property$1_offset
mustEqual(t, 0x8, "Token.property1 must start at 8")
t = Token.^property$2_offset
mustEqual(t, 12 as u32, "Token.property2 must start at 12")
t = Token.^allocationSize
mustEqual(t, 0x10, "Token.allocationSize must be 16")
END()
}
```
12 changes: 9 additions & 3 deletions src/compiler/phases/canonicalPhase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,8 +542,8 @@ const visitor = {
return new Nodes.IfNode(astNode, condition, truePart);
}
},
SyntaxError(_: Nodes.ASTNode) {
return null;
SyntaxError(node: Nodes.ASTNode) {
return new PositionCapableError(node.errors[0].message, node);
},
StructDirective(astNode: Nodes.ASTNode) {
const children = astNode.children.slice();
Expand Down Expand Up @@ -648,7 +648,13 @@ function visit<T extends Nodes.Node>(astNode: Nodes.ASTNode): T & any {
throw new Error('astNode is null');
}
if ((visitor as any)[astNode.type]) {
return (visitor as any)[astNode.type](astNode);
const x = (visitor as any)[astNode.type](astNode);

if (!x) {
throw new PositionCapableError('Error visiting node ' + astNode.type, astNode);
}

return x;
} else {
throw new PositionCapableError(`Visitor not implemented for ${astNode.type}`, astNode);
}
Expand Down
58 changes: 41 additions & 17 deletions src/compiler/phases/codeGenerationPhase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ function emit(node: Nodes.Node, document: Nodes.DocumentNode): any {
export class CodeGenerationPhaseResult {
programAST: any;
buffer?: Uint8Array;
sourceMap: string | null = null;

constructor(public document: Nodes.DocumentNode, public parsingContext: ParsingContext) {
failWithErrors(`Compilation`, parsingContext);
Expand Down Expand Up @@ -464,30 +465,53 @@ export class CodeGenerationPhaseResult {

const module = binaryen.readBinary(binary.buffer);

module.runPasses(['duplicate-function-elimination']);
if (!debug) {
module.runPasses(['duplicate-function-elimination']);
}
module.runPasses(['remove-unused-module-elements']);

if (module.validate() === 0) {
this.parsingContext.messageCollector.error(new LysCompilerError('binaryen validation failed', this.document));
}

let last = module.emitBinary();

if (optimize) {
do {
module.optimize();
let next = module.emitBinary();
if (next.length >= last.length) {
// a if (next.length > last.length) {
// a this.parsingContext.system.write('Last converge was suboptimial.\n');
// a }
break;
}
last = next;
} while (true);
}
if (debug) {
let last = module.emitBinary('sourceMap.map');

if (optimize) {
do {
module.optimize();
let next = module.emitBinary('sourceMap.map');
if (next.binary.length >= last.binary.length) {
// a if (next.length > last.length) {
// a this.parsingContext.system.write('Last converge was suboptimial.\n');
// a }
break;
}
last = next;
} while (true);
}

this.buffer = last;
this.buffer = last.binary;
this.sourceMap = last.sourceMap;
} else {
let last = module.emitBinary();

if (optimize) {
do {
module.optimize();
let next = module.emitBinary();
if (next.length >= last.length) {
// a if (next.length > last.length) {
// a this.parsingContext.system.write('Last converge was suboptimial.\n');
// a }
break;
}
last = next;
} while (true);
}

this.buffer = last;
}

module.dispose();

Expand Down
48 changes: 25 additions & 23 deletions src/compiler/phases/semanticPhase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ function explicitDecorator(
}

function processFunctionDecorations(node: Nodes.FunDirectiveNode, parsingContext: ParsingContext) {
if (node.decorators && node.decorators.length) {
if (node && node.decorators && node.decorators.length) {
node.decorators.forEach($ => {
switch ($.decoratorName.name) {
case 'extern':
Expand All @@ -153,7 +153,7 @@ function processFunctionDecorations(node: Nodes.FunDirectiveNode, parsingContext
}

function rejectDecorator(node: Nodes.DirectiveNode, parsingContext: ParsingContext) {
if (node.decorators && node.decorators.length) {
if (node && node.decorators && node.decorators.length) {
node.decorators.forEach($ => {
parsingContext.messageCollector.error(
`Unknown decorator "${$.decoratorName.name}" for ${node.nodeName}`,
Expand Down Expand Up @@ -190,30 +190,32 @@ const overloadFunctions = function(
document.directives[ix] = overloaded;
}
} else {
rejectDecorator(node, parsingContext);

if (node instanceof Nodes.ImplDirective) {
overloadFunctions(node, parsingContext);
} else if (node instanceof Nodes.TraitDirectiveNode) {
node.directives.forEach($ => {
if ($ instanceof Nodes.FunDirectiveNode) {
if ($.functionNode.body) {
parsingContext.messageCollector.error(
`Unexpected function body. Traits only accept signatures.`,
$.functionNode.body.astNode
);
}
if ($.decorators.length > 0) {
$.decorators.forEach($ => {
if (node) {
rejectDecorator(node, parsingContext);

if (node instanceof Nodes.ImplDirective) {
overloadFunctions(node, parsingContext);
} else if (node instanceof Nodes.TraitDirectiveNode) {
node.directives.forEach($ => {
if ($ instanceof Nodes.FunDirectiveNode) {
if ($.functionNode.body) {
parsingContext.messageCollector.error(
`Unexpected decorator. Traits only accept signatures.`,
$.astNode
`Unexpected function body. Traits only accept signatures.`,
$.functionNode.body.astNode
);
});
}
if ($.decorators.length > 0) {
$.decorators.forEach($ => {
parsingContext.messageCollector.error(
`Unexpected decorator. Traits only accept signatures.`,
$.astNode
);
});
}
}
}
});
overloadFunctions(node, parsingContext);
});
overloadFunctions(node, parsingContext);
}
}
}
});
Expand Down
Loading

0 comments on commit a4d2296

Please sign in to comment.