Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Commit

Permalink
enum support
Browse files Browse the repository at this point in the history
for #32
  • Loading branch information
mikeseese committed May 9, 2018
1 parent 3a56eff commit 3e47ea4
Show file tree
Hide file tree
Showing 12 changed files with 273 additions and 122 deletions.
27 changes: 21 additions & 6 deletions src/compilation/contractProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class ContractProcessor {
// are determined before we start using it in variable type definition
this.processContractChildType("InheritanceSpecifier");
this.processContractChildType("UsingForDirective");
this.processContractChildType("EnumDefinition");
this.processContractChildType("StructDefinition");
this.processContractChildType("VariableDeclaration");
this.processContractChildType("FunctionDefinition");
Expand Down Expand Up @@ -79,22 +80,32 @@ export class ContractProcessor {

private processContractStruct(node: any) {
// save the scope that the struct is defined at
this._contract.structDefinitions.set(node.attributes.name, node.id);
let structDefinition: LibSdbTypes.VariableMap = new Map<string, LibSdbTypes.Variable>();

const astWalker = new LibSdbUtils.AstWalker();
astWalker.walkDetail(node, null, 0, (node, parent, depth) => {
if (node.id) {
if (node.name === "VariableDeclaration") {
const variable = this.createVariableFromAst(node, parent, depth, null);
// add the variable to the parent's scope
if (!this._contract.scopeVariableMap.has(variable.scope.id)) {
this._contract.scopeVariableMap.set(variable.scope.id, new Map<string, LibSdbTypes.Variable>());
}
this._contract.scopeVariableMap.get(variable.scope.id)!.set(variable.name, variable);
structDefinition.set(variable.name, variable);
}
}

return true;
});

this._contract.structDefinitions.set(node.attributes.name, structDefinition);
}

private processContractEnum(node: any) {
// save the scope that the enum is defined at
let enumDefintion = new LibSdbTypes.EnumDefinition(node.attributes.name);

for (let i = 0; i < node.children.length; i++) {
enumDefintion.values.push(node.children[i].attributes.name);
}

this._contract.enumDefinitions.set(enumDefintion.name, enumDefintion);
}

private processContractFunction(node: any) {
Expand Down Expand Up @@ -145,6 +156,10 @@ export class ContractProcessor {
this.processContractStruct(node);
break;
}
case "EnumDefinition": {
this.processContractEnum(node);
break;
}
case "FunctionDefinition": {
this.processContractFunction(node);
break;
Expand Down
143 changes: 72 additions & 71 deletions src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,90 +167,91 @@ export class LibSdbRuntime extends EventEmitter {
else {
const contract = this._contractsByAddress.get(address);

if (!contract) {
this.respondToDebugHook("skipEvent");
return;
}
this._stepData = new LibSdbTypes.StepData();
this._stepData.debuggerMessageId = data.id;

// get line number from pc
const index = contract.pcMap.get(pc)!.index;
const sourceLocation = LibSdbUtils.SourceMappingDecoder.atIndex(index, contract.srcmapRuntime);
if (contract && contract.pcMap.has(pc)) {
// get line number from pc
const index = contract.pcMap.get(pc)!.index;
const sourceLocation = LibSdbUtils.SourceMappingDecoder.atIndex(index, contract.srcmapRuntime);

if (data.content.specialEvents.indexOf("fnJumpDestination") >= 0) {
this.processJumpIn(sourceLocation, contract, data.content.stack, true);
}
else if (data.content.specialEvents.indexOf("jump") >= 0) {
let processedJump: boolean = false;
if (this._priorStepData && this._priorStepData.source) {
if (this._priorStepData.source.jump === "i") {
this.processJumpIn(sourceLocation, contract, data.content.stack);
processedJump = true;
if (data.content.specialEvents.indexOf("fnJumpDestination") >= 0) {
this.processJumpIn(sourceLocation, contract, data.content.stack, true);
}
else if (data.content.specialEvents.indexOf("jump") >= 0) {
let processedJump: boolean = false;
if (this._priorStepData && this._priorStepData.source) {
if (this._priorStepData.source.jump === "i") {
this.processJumpIn(sourceLocation, contract, data.content.stack);
processedJump = true;
}
else if (this._priorStepData.source.jump === "o") {
await this.processJumpOut(contract, data.content.stack, data.content.memory);
processedJump = true;
}
}
else if (this._priorStepData.source.jump === "o") {
await this.processJumpOut(contract, data.content.stack, data.content.memory);
processedJump = true;

if (!processedJump && pc in contract.functionNames) {
// jump in to external function
// this is the JUMPDEST of a function we just entered
let frame = new LibSdbTypes.StackFrame();
frame.name = contract.functionNames[pc];
frame.file = contract.sourcePath;
frame.line = 0 //currentLocation.start === null ? null : currentLocation.start.line;
this._callStack.unshift(frame);
}
}

if (!processedJump && pc in contract.functionNames) {
// jump in to external function
// this is the JUMPDEST of a function we just entered
let frame = new LibSdbTypes.StackFrame();
frame.name = contract.functionNames[pc];
frame.file = contract.sourcePath;
frame.line = 0 //currentLocation.start === null ? null : currentLocation.start.line;
this._callStack.unshift(frame);
else if (data.content.specialEvents.indexOf("declaration") >= 0) {
this.processDeclaration(sourceLocation, contract, data.content.stack);
}
}
else if (data.content.specialEvents.indexOf("declaration") >= 0) {
this.processDeclaration(sourceLocation, contract, data.content.stack);
}

const fileId = sourceLocation.file;
let file: LibSdbTypes.File;
if (!isNaN(fileId)) {
file = this._filesById.get(fileId)!;
}
else {
file = this._files.get(contract.sourcePath)!;
}
const fileId = sourceLocation.file;
let file: LibSdbTypes.File;
if (!isNaN(fileId)) {
file = this._filesById.get(fileId)!;
}
else {
file = this._files.get(contract.sourcePath)!;
}

// find current scope
const currentScope = LibSdbUtils.findScope(sourceLocation.start, contract.ast);
// find current scope
const currentScope = LibSdbUtils.findScope(sourceLocation.start, contract.ast);

let currentLocation = {
start: null
};
if (file) {
currentLocation = LibSdbUtils.SourceMappingDecoder.convertOffsetToLineColumn(sourceLocation, file.lineBreaks);
}
let currentLocation = {
start: null
};
if (file) {
currentLocation = LibSdbUtils.SourceMappingDecoder.convertOffsetToLineColumn(sourceLocation, file.lineBreaks);
}

this._stepData = new LibSdbTypes.StepData();
this._stepData.debuggerMessageId = data.id;
this._stepData.source = sourceLocation;
this._stepData.location = currentLocation;
this._stepData.contractAddress = address;
this._stepData.vmData = CircularJSON.parse(CircularJSON.stringify(data.content)); // make a deep copy TODO: make this better
this._stepData.vmData.gasLeft = new BN(data.content.gasLeft);
this._stepData.vmData.stack = [];
for (let i = 0; i < data.content.stack.length; i++) {
this._stepData.vmData.stack.push(new BN(data.content.stack[i]));
}
this._stepData.scope = currentScope;
this._stepData.events = data.content.specialEvents;
if (data.exceptionError !== undefined) {
this._stepData.exception = data.exceptionError;
}
this._stepData.source = sourceLocation;
this._stepData.location = currentLocation;
this._stepData.scope = currentScope;
this._stepData.contractAddress = address;
this._stepData.vmData = CircularJSON.parse(CircularJSON.stringify(data.content)); // make a deep copy TODO: make this better
this._stepData.vmData.gasLeft = new BN(data.content.gasLeft);
this._stepData.vmData.stack = [];
for (let i = 0; i < data.content.stack.length; i++) {
this._stepData.vmData.stack.push(new BN(data.content.stack[i]));
}
this._stepData.events = data.content.specialEvents;
if (data.exceptionError !== undefined) {
this._stepData.exception = data.exceptionError;
}

if (!file) {
this.respondToDebugHook("skipEvent");
}
else if (data.content.specialEvents.length > 0 && data.content.specialEvents.indexOf("breakpoint") === -1 && data.exceptionError === undefined) {
// if there were any special events, none of them were a breakpoint, and there was no exception, skip the event
this.respondToDebugHook("skipEvent");
if (!file) {
this.respondToDebugHook("skipEvent");
}
else if (data.content.specialEvents.length > 0 && data.content.specialEvents.indexOf("breakpoint") === -1 && data.exceptionError === undefined) {
// if there were any special events, none of them were a breakpoint, and there was no exception, skip the event
this.respondToDebugHook("skipEvent");
}
else {
this.sendEvent("step");
}
}
else {
this.sendEvent("step");
this.respondToDebugHook("skipEvent");
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/types/barrel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ValueDetail, ArrayDetail, StructDetail, MappingDetail, ContractDetail } from "./barrel";
import { ValueDetail, ArrayDetail, StructDetail, MappingDetail, ContractDetail, EnumDetail } from "./barrel";

export * from "./astScope";
export * from "./breakpoint";
Expand All @@ -11,8 +11,11 @@ export * from "./stackFrame";
export * from "./stepData";
export * from "./variable/variable";
export * from "./variable/detail/value";
export * from "./variable/detail/enum";
export * from "./variable/detail/array";
export * from "./variable/detail/struct";
export * from "./variable/detail/mapping";
export * from "./variable/detail/contract";
export type VariableDetailType = ValueDetail | ArrayDetail | StructDetail | MappingDetail | ContractDetail;
export * from "./enum";

export type VariableDetailType = ValueDetail | EnumDetail | ArrayDetail | StructDetail | MappingDetail | ContractDetail;
18 changes: 15 additions & 3 deletions src/types/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export class Contract {
ast: Ast;
stateVariables: Variable[];
breakpoints: Map<number, number>;
structDefinitions: Map<string, number>;
structDefinitions: Map<string, LibSdbTypes.VariableMap>;
enumDefinitions: Map<string, LibSdbTypes.EnumDefinition>;
inheritedContracts: Contract[];

constructor() {
Expand All @@ -27,7 +28,8 @@ export class Contract {
this.stateVariables = [];
this.addresses = [];
this.breakpoints = new Map<number, number>();
this.structDefinitions = new Map<string, number>();
this.structDefinitions = new Map<string, Map<string, Variable>>();
this.enumDefinitions = new Map<string, LibSdbTypes.EnumDefinition>();
this.inheritedContracts = [];
}

Expand Down Expand Up @@ -69,7 +71,17 @@ export class Contract {
}

for (const v of this.structDefinitions) {
clone.structDefinitions.set(v[0], v[1]);
let definitionClone: LibSdbTypes.VariableMap = new Map<string, Variable>();

for (const v2 of v[1]) {
definitionClone.set(v2[0], v2[1].clone());
}

clone.structDefinitions.set(v[0], definitionClone);
}

for (const v of this.enumDefinitions) {
clone.enumDefinitions.set(v[0], v[1].clone());
}

for (let i = 0; i < this.inheritedContracts.length; i++) {
Expand Down
20 changes: 20 additions & 0 deletions src/types/enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

export class EnumDefinition {
public name: string;
public values: string[];

constructor(name: string) {
this.name = name;
this.values = [];
}

public clone(): EnumDefinition {
let clone = new EnumDefinition(this.name);

for (let i = 0; i < this.values.length; i++) {
clone.values.push(this.values[i]);
}

return clone;
}
}
6 changes: 3 additions & 3 deletions src/types/variable/decode/memory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { VariableType } from "../variable";
import { LibSdbTypes } from "../../types";
import { decode as decodeValue } from "./value";
import { BN } from "bn.js";

export function decode(stackPosition: number, memoryOffset: number, type: VariableType, stack: BN[], memory: (number | null)[]): string {
export function decode(stackPosition: number, memoryOffset: number, detail: LibSdbTypes.ValueDetail | LibSdbTypes.EnumDetail, stack: BN[], memory: (number | null)[]): string {
let v = "";

if (stackPosition !== null && stack.length > stackPosition) {
Expand All @@ -23,7 +23,7 @@ export function decode(stackPosition: number, memoryOffset: number, type: Variab
}
}).join("");
if (element) {
v = decodeValue(type, new BN(element, 16));
v = decodeValue(detail, new BN(element, 16));
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/types/variable/decode/stack.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { VariableType } from "../variable";
import { LibSdbTypes } from "../../types";
import { decode as decodeValue } from "./value";
import { BN } from "bn.js";

export function decode(position: number, type: VariableType, stack: BN[]): string {
export function decode(position: number, detail: LibSdbTypes.ValueDetail | LibSdbTypes.EnumDetail, stack: BN[]): string {
if (position !== null && position >= 0 && position < stack.length) {
// stack
return decodeValue(type, stack[position]);
return decodeValue(detail, stack[position]);
}
else {
return "";
Expand Down
6 changes: 3 additions & 3 deletions src/types/variable/decode/storage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { LibSdbInterface } from "../../../interface";
import { VariableType } from "../variable";
import { LibSdbTypes } from "../../types";
import { decode as decodeValue } from "./value";
import { BN } from "bn.js";

export async function decode(position: number, offset: number, length: number, type: VariableType, _interface: LibSdbInterface, address: string): Promise<string> {
export async function decode(position: number, offset: number, length: number, detail: LibSdbTypes.ValueDetail | LibSdbTypes.EnumDetail, _interface: LibSdbInterface, address: string): Promise<string> {
let value = "";

if (position === null) {
Expand All @@ -21,7 +21,7 @@ export async function decode(position: number, offset: number, length: number, t
if (end < 0) {
end = 0;
}
value = decodeValue(type, new BN(content.value.slice(start, end)));
value = decodeValue(detail, new BN(content.value.slice(start, end)));
}

return value;
Expand Down
Loading

0 comments on commit 3e47ea4

Please sign in to comment.