Skip to content

Commit

Permalink
Add Location type
Browse files Browse the repository at this point in the history
  • Loading branch information
huynhtrankhanh committed Jul 31, 2023
1 parent c9418a1 commit 5f2c0f0
Showing 1 changed file with 49 additions and 49 deletions.
98 changes: 49 additions & 49 deletions compiler/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ class ParseError extends Error {
}
}

const formatLocation = ({
start,
end,
}: {
type Location = {
start: { line: number; column: number };
end: { line: number; column: number };
}): string => `${start.line}:${start.column}-${end.line}:${end.column}`;
};

const formatLocation = ({ start, end }: Location): string =>
`${start.line}:${start.column}-${end.line}:${end.column}`;

interface Procedure {
name: string;
Expand Down Expand Up @@ -117,43 +117,43 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
'only "environment" and "procedure" expressions allowed. ' +
formatLocation(node.loc),
formatLocation(node.loc)
);
}

if (node.expression.callee.name === "environment") {
if (seenEnvironmentBlock) {
throw new ParseError(
"duplicate environment block. " + formatLocation(node.loc),
"duplicate environment block. " + formatLocation(node.loc)
);
}
seenEnvironmentBlock = true;

if (node.expression.arguments.length !== 1) {
throw new ParseError(
"environment block accepts exactly 1 argument. " +
formatLocation(node.loc),
formatLocation(node.loc)
);
}

const argumentNode = node.expression.arguments[0];
if (argumentNode.type !== "ObjectExpression") {
throw new ParseError(
"the argument must be an object. " +
formatLocation(argumentNode.loc),
formatLocation(argumentNode.loc)
);
}

for (const property of argumentNode.properties) {
if (property.type === "SpreadElement") {
throw new ParseError(
"spread syntax isn't recognized. " + formatLocation(property.loc),
"spread syntax isn't recognized. " + formatLocation(property.loc)
);
}

if (property.key.type !== "Identifier") {
throw new ParseError(
"unrecognized key type. " + formatLocation(property.key.loc),
"unrecognized key type. " + formatLocation(property.key.loc)
);
}

Expand All @@ -165,14 +165,14 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"expecting an array expression. " +
formatLocation(arrayDescription.loc),
formatLocation(arrayDescription.loc)
);
}

if (arrayDescription.arguments.length !== 2) {
throw new ParseError(
"array() accepts exactly two arguments. " +
formatLocation(arrayDescription.loc),
formatLocation(arrayDescription.loc)
);
}

Expand All @@ -182,7 +182,7 @@ class CoqCPASTTransformer {
if (typesArrayNode.type !== "ArrayExpression") {
throw new ParseError(
"first argument of array() must be an array." +
formatLocation(typesArrayNode.loc),
formatLocation(typesArrayNode.loc)
);
}

Expand All @@ -192,7 +192,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"second argument of array() must be a numeric literal." +
formatLocation(lengthNode.loc),
formatLocation(lengthNode.loc)
);
}

Expand All @@ -208,7 +208,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"invalid array item type. range: " +
formatLocation(typesArrayNode.loc),
formatLocation(typesArrayNode.loc)
);
}

Expand All @@ -230,7 +230,7 @@ class CoqCPASTTransformer {
if (node.expression.arguments.length !== 3) {
throw new ParseError(
"procedure block accepts exactly 3 arguments. " +
formatLocation(node.loc),
formatLocation(node.loc)
);
}

Expand All @@ -244,14 +244,14 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"first argument of procedure() must be a string literal. " +
formatLocation(procedureNameNode.loc),
formatLocation(procedureNameNode.loc)
);
}

if (variableListNode.type !== "ObjectExpression") {
throw new ParseError(
"second argument of procedure() must be an object. " +
formatLocation(variableListNode.loc),
formatLocation(variableListNode.loc)
);
}

Expand All @@ -260,19 +260,19 @@ class CoqCPASTTransformer {
for (const property of variableListNode.properties) {
if (property.type === "SpreadElement") {
throw new ParseError(
"spread syntax isn't recognized. " + formatLocation(property.loc),
"spread syntax isn't recognized. " + formatLocation(property.loc)
);
}

if (property.key.type !== "Identifier") {
throw new ParseError(
"unrecognized key type. " + formatLocation(property.key.loc),
"unrecognized key type. " + formatLocation(property.key.loc)
);
}

if (property.value.type !== "Identifier") {
throw new ParseError(
"unrecognized value type. " + formatLocation(property.value.loc),
"unrecognized value type. " + formatLocation(property.value.loc)
);
}

Expand All @@ -286,7 +286,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"third argument of procedure() must be an arrow function expression. " +
formatLocation(bodyNode.loc),
formatLocation(bodyNode.loc)
);
}

Expand All @@ -308,7 +308,7 @@ class CoqCPASTTransformer {
}

private processNode(
node: ExtendNode<ESTree.Node>,
node: ExtendNode<ESTree.Node>
): Instruction | LocalBinder | number {
if (node.type === "CallExpression" && node.callee.type === "Identifier") {
return this.processInstruction(
Expand All @@ -320,7 +320,7 @@ class CoqCPASTTransformer {

return x;
}),
node.loc,
node.loc
);
} else if (node.type === "Identifier") {
return { type: "local binder", name: node.name };
Expand All @@ -332,18 +332,18 @@ class CoqCPASTTransformer {
const instruction = this.processNode(node.object);
if (node.property.type !== "Literal") {
throw new ParseError(
"only literal indices allowed. " + formatLocation(node.loc),
"only literal indices allowed. " + formatLocation(node.loc)
);
}
const index = node.property.raw;
if (index === undefined) {
throw new ParseError(
"index must be defined. " + formatLocation(node.loc),
"index must be defined. " + formatLocation(node.loc)
);
}
if (typeof instruction === "string" || typeof instruction === "number") {
throw new ParseError(
"left hand side can't be a literal. " + formatLocation(node.loc),
"left hand side can't be a literal. " + formatLocation(node.loc)
);
}
return { type: "subscript", value: instruction, index: Number(index) };
Expand All @@ -353,7 +353,7 @@ class CoqCPASTTransformer {
}

private processBinaryExpression(
node: ExtendNode<ESTree.BinaryExpression>,
node: ExtendNode<ESTree.BinaryExpression>
): BinaryOperationInstruction {
const operator = this.getBinaryOperator(node.operator, node.loc);
const left = this.processNode(node.left);
Expand All @@ -372,7 +372,7 @@ class CoqCPASTTransformer {
line: number;
column: number;
};
},
}
): BinaryOp {
switch (operator) {
case "+":
Expand Down Expand Up @@ -402,7 +402,7 @@ class CoqCPASTTransformer {
"invalid binary operator: " +
operator +
". " +
formatLocation(location),
formatLocation(location)
);
}
}
Expand All @@ -419,7 +419,7 @@ class CoqCPASTTransformer {
line: number;
column: number;
};
},
}
): Instruction {
let instruction: Instruction;

Expand All @@ -432,7 +432,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"get() function accepts exactly 1 string argument. " +
formatLocation(location),
formatLocation(location)
);
}
const varName = args[0].value;
Expand All @@ -448,7 +448,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"set() function accepts exactly 2 arguments, first one being a string. " +
formatLocation(location),
formatLocation(location)
);
}
const varName = args[0].value;
Expand All @@ -466,7 +466,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"store() function accepts exactly 3 arguments, first one being a string and last one being an array. " +
formatLocation(location),
formatLocation(location)
);
}
const arrayName = args[0].value;
Expand All @@ -477,7 +477,7 @@ class CoqCPASTTransformer {
}
if (node.type === "SpreadElement") {
throw new Error(
"spread syntax not supported, " + formatLocation(location),
"spread syntax not supported, " + formatLocation(location)
);
}
return this.processNode(node as ExtendNode<ESTree.Expression>);
Expand All @@ -494,7 +494,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"retrieve() function accepts exactly 2 arguments, first one being a string. " +
formatLocation(location),
formatLocation(location)
);
}
const arrayName = args[0].value;
Expand All @@ -511,7 +511,7 @@ class CoqCPASTTransformer {
) {
throw new ParseError(
"range() function accepts exactly 2 arguments, second one being an arrow function. " +
formatLocation(location),
formatLocation(location)
);
}
const end = this.processNode(args[0]);
Expand All @@ -520,23 +520,23 @@ class CoqCPASTTransformer {
if (funcNode.params.length !== 1) {
throw new ParseError(
"arrow function must take exactly 1 argument. " +
formatLocation(funcNode.loc),
formatLocation(funcNode.loc)
);
}

const parameter = funcNode.params[0];

if (parameter.type !== "Identifier") {
throw new ParseError(
"this parameter isn't recognized. " + formatLocation(parameter.loc),
"this parameter isn't recognized. " + formatLocation(parameter.loc)
);
}

const loopVariable = parameter.name;

if (funcNode.body.type !== "BlockStatement") {
throw new ParseError(
"block statement expected. " + formatLocation(funcNode.loc),
"block statement expected. " + formatLocation(funcNode.loc)
);
}

Expand All @@ -555,7 +555,7 @@ class CoqCPASTTransformer {
if (args.length !== 0) {
throw new ParseError(
"readInt8() function accepts exactly 0 argument. " +
formatLocation(location),
formatLocation(location)
);
}
instruction = { type: "readInt8" };
Expand All @@ -566,7 +566,7 @@ class CoqCPASTTransformer {
if (args.length !== 1) {
throw new ParseError(
"writeInt8() function accepts exactly 1 argument. " +
formatLocation(location),
formatLocation(location)
);
}
const value = this.processNode(args[0]);
Expand All @@ -576,15 +576,15 @@ class CoqCPASTTransformer {

default:
throw new ParseError(
"unknown instruction: " + name + ". " + formatLocation(location),
"unknown instruction: " + name + ". " + formatLocation(location)
);
}

return instruction;
}

private transformBodyNode(
bodyNode: ExtendNode<ESTree.BlockStatement>,
bodyNode: ExtendNode<ESTree.BlockStatement>
): Instruction[] {
let instructions: Instruction[] = [];

Expand All @@ -594,7 +594,7 @@ class CoqCPASTTransformer {
if (statement.consequent.type !== "BlockStatement") {
throw new Error(
"must be a block statement. " +
formatLocation(statement.consequent.loc),
formatLocation(statement.consequent.loc)
);
}
const consequent = this.transformBodyNode(statement.consequent);
Expand All @@ -613,15 +613,15 @@ class CoqCPASTTransformer {
throw new Error("must be a block statement. " + statement.loc);
}
throw new Error(
"must be a block statement. " + formatLocation(alternate.loc),
"must be a block statement. " + formatLocation(alternate.loc)
);
}
instructions.push({
type: "condition",
condition: test,
body: consequent,
alternate: this.transformBodyNode(
alternate as ExtendNode<ESTree.BlockStatement>,
alternate as ExtendNode<ESTree.BlockStatement>
),
});
continue;
Expand All @@ -631,7 +631,7 @@ class CoqCPASTTransformer {
statement.expression.type !== "CallExpression"
) {
throw new ParseError(
"invalid statement type. " + formatLocation(statement.loc),
"invalid statement type. " + formatLocation(statement.loc)
);
}
instructions.push(this.processNode(statement.expression) as Instruction);
Expand Down

0 comments on commit 5f2c0f0

Please sign in to comment.