Skip to content
This repository was archived by the owner on Oct 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #24 from shashankbhosagi/main
Browse files Browse the repository at this point in the history
✨ New test cases, A native function (assertEqual) for testing, Introduced new keywords assemble & snap.
  • Loading branch information
SahilK-027 authored Aug 4, 2023
2 parents d77cbde + b942433 commit b9c33dd
Show file tree
Hide file tree
Showing 6 changed files with 402 additions and 228 deletions.
50 changes: 50 additions & 0 deletions BackEnd/Scope/globalScope.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
BooleanVal,
MAKE_BOOL,
MAKE_FUNCTION,
MAKE_NATIVE_FN,
MAKE_NUll,
MAKE_NUM,
Expand All @@ -12,6 +13,17 @@ import {
import Environment from "./environment.ts";

export function setupGlobalScope() {
const isVaild = (actual: any, expected: any): RuntimeVal => {
if (actual === expected) {
console.log("✅Test passed!");
return MAKE_BOOL(true);
} else {
console.log("❌Test failed!");
console.log("⚠️ Expected: ", expected);
console.log("⚠️ Output: ", actual);
throw `Failed execution`;
}
};
const env = new Environment();
/** ===========================================================================================
* Definition of global constant variables and builtin methods
Expand All @@ -22,6 +34,44 @@ export function setupGlobalScope() {
env.declareVar("null", MAKE_NUll(), true);

// Define a native builtin method GENERAL
env.declareVar(
"assertEqual",
MAKE_NATIVE_FN((args, _scope): RuntimeVal => {
if (args.length !== 2) {
const error_msg: any =
`No matching function for call to 'assertEqual'. Note: candidate function not viable. Function assertEqual requires 2 arguments, but ${args.length} was provided.`;
throw error_msg;
}
const actual_type = args[0].type;
const expected_type = args[1].type;

if (actual_type !== expected_type) {
throw `❌Test failed (Type Mismatched)`;
} else {
switch (actual_type) {
case "string": {
const actual = (args[0] as StringVal).value;
const expected = (args[1] as StringVal).value;
return isVaild(actual, expected);
}
case "number": {
const actual = (args[0] as NumberVal).value;
const expected = (args[1] as NumberVal).value;
return isVaild(actual, expected);
}
case "boolean": {
const actual = (args[0] as BooleanVal).value;
const expected = (args[1] as BooleanVal).value;
return isVaild(actual, expected);
}

default:
throw `Error: Null value exception`;
}
}
}),
true,
);
env.declareVar(
"vision",
MAKE_NATIVE_FN((args, _scope): RuntimeVal => {
Expand Down
37 changes: 20 additions & 17 deletions FrontEnd/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ export default class Parser {
return this.parse_switch_statement();
case TokenType.WakandaFor:
return this.parse_for_loop_statement();
case TokenType.Def:
case TokenType.Assemble:
return this.parse_function_definition();
case TokenType.Return:
case TokenType.Snap:
return this.parse_return_statement();

default: {
Expand All @@ -151,8 +151,10 @@ export default class Parser {
* @throws {Error} If there are syntax errors or missing tokens in the parameter.
*/
private parse_function_param(): FunctionParam {
const name =
this.expect(TokenType.Identifier, "Expected parameter name").value;
const name = this.expect(
TokenType.Identifier,
"Expected parameter name",
).value;
return { kind: "FunctionParam", name };
}

Expand All @@ -163,10 +165,12 @@ export default class Parser {
* @throws {Error} If there are syntax errors or missing tokens in the function definition.
*/
private parse_function_definition(): FunctionDefinition {
this.eat(); // Eat 'def' token
this.eat(); // Eat 'assemble' token

const name =
this.expect(TokenType.Identifier, "Expected function name").value;
const name = this.expect(
TokenType.Identifier,
"Expected function name",
).value;

this.expect(
TokenType.OpenParen,
Expand Down Expand Up @@ -216,7 +220,7 @@ export default class Parser {
* @throws {Error} If there are syntax errors or missing tokens in the return statement.
*/
private parse_return_statement(): ReturnStatement {
this.eat(); // Eat 'return' token
this.eat(); // Eat 'snap' token

let value: Expr | undefined = undefined;
if (this.at().type !== TokenType.Semicolon) {
Expand Down Expand Up @@ -385,7 +389,8 @@ export default class Parser {
while (
this.at().type !== TokenType.Madness &&
this.at().type !== TokenType.Default &&
this.at().type !== TokenType.CloseBrace && this.not_eof()
this.at().type !== TokenType.CloseBrace &&
this.not_eof()
) {
consequent.push(this.parse_stmt());
}
Expand All @@ -402,7 +407,8 @@ export default class Parser {
while (
this.at().type !== TokenType.Madness &&
this.at().type !== TokenType.Default &&
this.at().type !== TokenType.CloseBrace && this.not_eof()
this.at().type !== TokenType.CloseBrace &&
this.not_eof()
) {
defaultCase.push(this.parse_stmt());
}
Expand Down Expand Up @@ -746,9 +752,7 @@ export default class Parser {
private parse_comparison_expr(): Expr {
let left = this.parse_additive_expr();

while (
this.at().type === TokenType.ComparisonOperator
) {
while (this.at().type === TokenType.ComparisonOperator) {
const operator = this.eat().value; // Consume the comparison operator token
const right = this.parse_additive_expr(); // Parse the right-hand side of the comparison

Expand Down Expand Up @@ -797,7 +801,8 @@ export default class Parser {

// Pase operator
while (
this.at().value === "*" || this.at().value === "/" ||
this.at().value === "*" ||
this.at().value === "/" ||
this.at().value === "%"
) {
const operator = this.eat().value;
Expand All @@ -821,9 +826,7 @@ export default class Parser {
let left = this.parse_call_member_expr();

// Pase operator
while (
this.at().value === "^"
) {
while (this.at().value === "^") {
const operator = this.eat().value;
const right = this.parse_call_member_expr();

Expand Down
28 changes: 14 additions & 14 deletions FrontEnd/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ export enum TokenType {
In,
To,
Step,
Def,
// TODO: Change Return name to Snap
Return,
Assemble,
Snap,
// Operators + Other tokens
Equals,
Semicolon,
Expand Down Expand Up @@ -68,9 +67,8 @@ const KEYWORDS: Record<string, TokenType> = {
step: TokenType.Step,
and: TokenType.LogicalOperator,
or: TokenType.LogicalOperator,
def: TokenType.Def,
// TODO: Change Return name to Snap
return: TokenType.Return,
assemble: TokenType.Assemble,
snap: TokenType.Snap,
};

/**
Expand Down Expand Up @@ -116,10 +114,7 @@ function isNum(src: string): boolean {
function isAlphabet(src: string): boolean {
const c = src.charCodeAt(0);
const underscore = "_".charCodeAt(0);
return (
src.toUpperCase() !== src.toLowerCase() ||
c === underscore
);
return src.toUpperCase() !== src.toLowerCase() || c === underscore;
}

/**
Expand Down Expand Up @@ -176,8 +171,9 @@ function getMultiCharacterToken(src: string[]): Token | null {
* @returns True if the string represents a skippable character, false otherwise.
*/
function isSkippable(src: string): boolean {
return src === " " || src === "\n" || src === "\t" || src === "\r" ||
src === '"';
return (
src === " " || src === "\n" || src === "\t" || src === "\r" || src === '"'
);
}

/**
Expand Down Expand Up @@ -219,8 +215,12 @@ export function tokenize(sourceCode: string): Token[] {
} else if (src[0] === "]") {
tokens.push(getToken(src.shift(), TokenType.CloseBracket));
} else if (
src[0] === "+" || src[0] === "-" || src[0] === "*" || src[0] === "/" ||
src[0] === "%" || src[0] === "^"
src[0] === "+" ||
src[0] === "-" ||
src[0] === "*" ||
src[0] === "/" ||
src[0] === "%" ||
src[0] === "^"
) {
tokens.push(getToken(src.shift(), TokenType.BinaryOperator));
} else if (src[0] === ";") {
Expand Down
2 changes: 1 addition & 1 deletion feat.avenger
Original file line number Diff line number Diff line change
@@ -1 +1 @@
vision("Hello");
vision("Hello Avenger!");
2 changes: 1 addition & 1 deletion main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async function __run(inputFile: string) {
const program = parser.produceAST(input);
evaluate(program, env);
}
__run("./feat.avenger");
__run("./test.avenger");
/**
* Initializes the script execution.
*/
Expand Down
Loading

0 comments on commit b9c33dd

Please sign in to comment.