Skip to content

Commit

Permalink
feat: catch redeclaration error (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
shenyih0ng authored Apr 17, 2024
1 parent d5ce459 commit 5779ea3
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 5 deletions.
16 changes: 16 additions & 0 deletions src/go-slang/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ export class UndefinedError extends RuntimeSourceError {
}
}

export class RedeclarationError extends RuntimeSourceError {
private identifier: string

public location: NodeLocation

constructor(identifier: string, location: NodeLocation) {
super()
this.identifier = identifier
this.location = location
}

public explain() {
return `${this.identifier} redeclared in this block`
}
}

export class AssignmentOperationError extends RuntimeSourceError {
public location: NodeLocation

Expand Down
15 changes: 10 additions & 5 deletions src/go-slang/goroutine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
GoExprMustBeFunctionCallError,
InternalError,
InvalidOperationError,
RedeclarationError,
UndefinedError,
UnknownInstructionError
} from './error'
Expand Down Expand Up @@ -306,7 +307,7 @@ const Interpreter: {

TypeLiteral: (inst: TypeLiteral, { S }) => S.push(inst),

Identifier: ({ name, loc }: Identifier, { S, E, H }) => {
Identifier: ({ name, loc }: Identifier, { S, E }) => {
const value = E.lookup(name)
return value === null ? Result.fail(new UndefinedError(name, loc!)) : S.push(value)
},
Expand Down Expand Up @@ -374,12 +375,16 @@ const Interpreter: {
ExpressionStatement: ({ expression }: ExpressionStatement, { C, H }) =>
C.pushR(...H.allocM([expression, PopS])),

VarDeclOp: ({ idNodeUid, zeroValue }: VarDeclOp, { S, E, H, A }) => {
const name = A.get<Identifier>(idNodeUid).name
zeroValue ? E.declareZeroValue(name) : E.declare(name, S.pop())
VarDeclOp: ({ idNodeUid, zeroValue }: VarDeclOp, { S, E, A }) => {
const id = A.get<Identifier>(idNodeUid)
const name = id.name
if (E.declaredInBlock(name)) {
return Result.fail(new RedeclarationError(name, id.loc!))
}
return void zeroValue ? E.declareZeroValue(name) : E.declare(name, S.pop())
},

AssignOp: ({ idNodeUid }: AssignOp, { S, E, H, A }) => {
AssignOp: ({ idNodeUid }: AssignOp, { S, E, A }) => {
const id = A.get<Identifier>(idNodeUid)
!E.assign(id.name, S.pop()) ? new UndefinedError(id.name, id.loc!) : void {}
},
Expand Down
4 changes: 4 additions & 0 deletions src/go-slang/lib/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class Environment {
return this
}

public declaredInBlock(name: string): boolean {
return this.currFrame.bindings.has(name)
}

public copy(): Environment {
const newEnv = new Environment()
newEnv.frameMap = this.frameMap
Expand Down

0 comments on commit 5779ea3

Please sign in to comment.