Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/david518yang/Lang
Browse files Browse the repository at this point in the history
  • Loading branch information
Mattmart42 committed Apr 29, 2024
2 parents 434e5c4 + 871bf59 commit afb2994
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 34 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# MODE

[Mode Official Website](https://david518yang.github.io/MODEsite/)

## Matt Martinez, Owen Sheow, David Yang, Eric Hwang

## Story/Introduction
Expand Down
2 changes: 1 addition & 1 deletion src/MODE.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ MODE {
| LoopStmt
| BreakStmt
| ClassDef
| return ";" --shortreturn
| return Exp ";" --return
| return ";" --shortreturn

VarDecl = auto id "=" Exp ";" --inference
| Type id "=" Exp ";" --type
Expand Down
11 changes: 9 additions & 2 deletions src/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ export default function analyze(match) {
return 'string'
case 'BoolType':
return 'boolean'
case 'AnyType':
return 'any'
// case 'AnyType':
// return 'any'
case 'ClassType':
return type.name
case 'ArrayType':
Expand Down Expand Up @@ -560,6 +560,13 @@ export default function analyze(match) {
return core.binary(op, left, right, left.type)
},

Factor_negation(unaryOp, exp) {
const [op, operand] = [unaryOp.sourceString, exp.rep()]
mustHaveNumericType(operand, { at: exp })
let type = operand.type
return core.negation(op, operand, type)
},

Primary_emptyarray(ty, _open, _close) {
const type = ty.rep()
mustBeAnArrayType(type, { at: ty })
Expand Down
4 changes: 2 additions & 2 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ export function binary(op, left, right, type) {
return { kind: 'BinaryExpression', op, left, right, type }
}

export function unary(op, operand, type) {
return { kind: 'UnaryExpression', op, operand, type }
export function negation(op, operand, type) {
return { kind: 'NegationExpression', op, operand, type }
}

export function emptyOptional(baseType) {
Expand Down
21 changes: 7 additions & 14 deletions src/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ export default function generate(program) {
output.push("}")
output.push("}")
},
StructType(t) {
return targetName(t)
},
// StructType(t) {
// return targetName(t)
// },
Field(f) {
return targetName(f)
},
Expand Down Expand Up @@ -116,22 +116,15 @@ export default function generate(program) {
s.body.forEach(gen)
output.push("}")
},
Conditional(e) {
return `((${gen(e.test)}) ? (${gen(e.consequent)}) : (${gen(e.alternate)}))`
},
// Conditional(e) {
// return `((${gen(e.test)}) ? (${gen(e.consequent)}) : (${gen(e.alternate)}))`
// },
BinaryExpression(e) {
const op = { "==": "===", "!=": "!==" }[e.op] ?? e.op
return `(${gen(e.left)} ${op} ${gen(e.right)})`
},
UnaryExpression(e) {
NegationExpression(e) {
const operand = gen(e.operand)
if (e.op === "some") {
return operand
} else if (e.op === "#") {
return `${operand}.length`
} else if (e.op === "random") {
return `((a=>a[~~(Math.random()*a.length)])(${operand}))`
}
return `${e.op}(${operand})`
},
SubscriptExpression(e) {
Expand Down
4 changes: 2 additions & 2 deletions src/optimizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ const optimizers = {
else if (e.op === ">") return e.left > e.right
} else if (e.left === 0 && e.op === "+") return e.right
else if (e.left === 1 && e.op === "*") return e.right
else if (e.left === 0 && e.op === "-") return core.unary("-", e.right)
else if (e.left === 0 && e.op === "-") return core.negation("-", e.right)
else if (e.left === 1 && e.op === "**") return 1
else if (e.left === 0 && ["*", "/"].includes(e.op)) return 0
} else if ([Number, BigInt].includes(e.right.constructor)) {
Expand All @@ -169,7 +169,7 @@ const optimizers = {
}
return e
},
UnaryExpression(e) {
NegationExpression(e) {
e.op = optimize(e.op)
e.operand = optimize(e.operand)
if (e.operand.constructor === Number) {
Expand Down
1 change: 1 addition & 0 deletions test/analyzer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const semanticChecks = [
'type description for array type',
'int[] arr = [1, 2, 3]; arr = [2, 3, 4];',
],
['unary negation', 'auto x = -5;']
]

// Programs that are syntactically correct but have semantic errors
Expand Down
17 changes: 9 additions & 8 deletions test/generator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@ const fixtures = [
{
name: "functions",
source: `
auto z = 0.5;
func f(x: float, y: bool) {
print x;
return;
}
func g(): bool {
return false;
}
auto z = 0.5;
func f(x: float, y: bool) {
print x;
return;
}
func g(): bool {
return false;
}
f(z, g());
`,
expected: dedent`
let z_1 = 0.5;
Expand Down
10 changes: 5 additions & 5 deletions test/optimizer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ const and = (...c) => c.reduce((x, y) => core.binary("&&", x, y))
const less = (x, y) => core.binary("<", x, y)
const eq = (x, y) => core.binary("==", x, y)
const times = (x, y) => core.binary("*", x, y)
const neg = x => core.unary("-", x)
const neg = x => core.negation("-", x)
const array = (...elements) => core.arrayExpression(elements)
const assign = (v, e) => core.assignment(v, e)
const emptyArray = core.emptyArray(core.intType)
const sub = (a, e) => core.subscript(a, e)
const unwrapElse = (o, e) => core.binary("??", o, e)
const emptyOptional = core.emptyOptional(core.intType)
const some = x => core.unary("some", x)
const program = core.program

const tests = [
Expand All @@ -50,7 +49,7 @@ const tests = [
["optimizes 0+", core.binary("+", 0, x), x],
["optimizes 0-", core.binary("-", 0, x), neg(x)],
["optimizes 1*", core.binary("*", 1, x), x],
["folds negation", core.unary("-", 8), -8],
["folds negation", core.negation("-", 8), -8],
["optimizes 1**", core.binary("**", 1, x), 1],
["optimizes **0", core.binary("**", x, 0), 1],
["removes left false from ||", or(false, less(x, 1)), less(x, 1)],
Expand All @@ -66,26 +65,27 @@ const tests = [
["optimizes in arguments", callIdentity([times(3, 5)]), callIdentity([15])],
["optimizes ConstructorCall", core.constructorCall(identity, [times(3, 5)]), core.constructorCall(identity, [15])],
["optimizes MemberExpression", core.memberExpression(core.constructorCall(identity, [times(3, 5)]), ".", "f"), core.memberExpression(core.constructorCall(identity, [15]), ".", "f")],
["optimizes assignments return brackets", core.program([assign(x, core.binary("+", x, 1)), returnX]), core.program([assign(x, core.binary("+", x, 1)), returnX])],
[
"passes through nonoptimizable constructs",
...Array(2).fill([
core.program([core.shortReturnStatement()]),
core.variableDeclaration("x", true, "z"),
core.assignment(x, core.binary("*", x, "z")),
core.assignment(x, core.unary("not", x)),
core.assignment(x, core.negation("not", x)),
core.constructorCall(identity, core.memberExpression(x, ".", "f")),
core.variableDeclaration("q", false, core.emptyArray(core.floatType)),
core.variableDeclaration("r", false, core.emptyOptional(core.intType)),
core.whileStatement(true, [core.breakStatement]),
core.conditional(x, 1, 2),
unwrapElse(some(x), 7),
core.ifStatement(x, [], []),
core.shortIfStatement(x, []),
core.forRangeStatement(x, 2, "..", 5, []),
core.forStatement(x, array(1, 2, 3), []),
]),
],
["optimizes whileStatement", core.whileStatement(true, [returnX]), core.whileStatement(true, [returnX])],
["optimizes shortReturnStatement", core.shortReturnStatement(), core.shortReturnStatement()],
]

describe("The optimizer", () => {
Expand Down

0 comments on commit afb2994

Please sign in to comment.