public HassiumExceptionHandler(HassiumMethod caller, HassiumMethod handler, int label) { Caller = caller; Handler = handler; Label = label; AddType(TypeDefinition); }
public HassiumThread(VirtualMachine vm, HassiumMethod method, StackFrame.Frame frame) { VirtualMachine newVM = vm.Clone() as VirtualMachine; newVM.ExceptionReturns = new Dictionary<HassiumMethod, int>(); newVM.Handlers = new Stack<HassiumExceptionHandler>(); newVM.Stack = new Stack<HassiumObject>(); newVM.StackFrame = new StackFrame(); Thread = new Thread(() => ReturnValue = method.Invoke(newVM, frame)); AddType(TypeDefinition); AddAttribute("isAlive", new HassiumProperty(get_isAlive)); AddAttribute("returnValue", new HassiumProperty(get_returnValue)); AddAttribute("start", start, 0); AddAttribute("stop", stop, 0); }
public HassiumObject ExecuteMethod(HassiumMethod method) { for (int pos = 0; pos < method.Instructions.Count; pos++) { if (ExceptionReturns.ContainsKey(method)) { pos = ExceptionReturns[method]; ExceptionReturns.Remove(method); } HassiumObject left, right, val, list; HassiumObject[] elements; string attrib; int arg = method.Instructions[pos].Argument; CurrentSourceLocation = method.Instructions[pos].SourceLocation; //Console.WriteLine(method.Instructions[pos].ToString()); try { switch (method.Instructions[pos].InstructionType) { case InstructionType.BinaryOperation: right = Stack.Pop(); left = Stack.Pop(); interpretBinaryOperation(left, right, arg); break; case InstructionType.BuildClosure: Stack.Push(new HassiumClosure(Stack.Pop() as HassiumMethod, StackFrame.Frames.Peek())); break; case InstructionType.BuildDictionary: List<HassiumKeyValuePair> pairs = new List<HassiumKeyValuePair>(); for (int i = 0; i < arg; i++) pairs.Add(Stack.Pop() as HassiumKeyValuePair); Stack.Push(new HassiumDictionary(pairs)); break; case InstructionType.BuildKeyValuePair: Stack.Push(new HassiumKeyValuePair(Stack.Pop(), Stack.Pop())); break; case InstructionType.BuildLabel: Stack.Push(new HassiumLabel(arg)); break; case InstructionType.BuildList: elements = new HassiumObject[arg]; for (int i = elements.Length - 1; i >= 0; i--) elements[i] = Stack.Pop(); Stack.Push(new HassiumList(elements)); break; case InstructionType.BuildThread: Stack.Push(new HassiumThread(this, CurrentModule.ObjectPool[arg] as HassiumMethod, StackFrame.Frames.Peek())); break; case InstructionType.BuildTuple: HassiumObject[] tupleElements = new HassiumObject[arg]; for (int i = 0; i < arg; i++) tupleElements[i] = Stack.Pop(); Stack.Push(new HassiumTuple(tupleElements)); break; case InstructionType.Call: val = Stack.Pop(); elements = new HassiumObject[arg]; for (int i = elements.Length - 1; i >= 0; i--) elements[i] = Stack.Pop(); Stack.Push(val.Invoke(this, elements)); break; case InstructionType.Dereference: Stack.Push(((HassiumPointer)Stack.Pop()).Dereference()); break; case InstructionType.Dispose: Stack.Pop().Dispose(this); break; case InstructionType.Duplicate: Stack.Push(Stack.Peek()); break; case InstructionType.EnforcedAssignment: var type = Globals[Stack.Pop().ToString(this).String].Type(); val = Stack.Pop(); if (!val.Types.Contains(type)) throw new InternalException(this, "Expcted assignment type {0}, got {1}!", type, val.Type()); if (StackFrame.Contains(arg)) StackFrame.Modify(arg, val); else StackFrame.Add(arg, val); Stack.Push(val); break; case InstructionType.Goto: pos = (int)Stack.Pop().ToInt(this).Int; break; case InstructionType.Iter: Stack.Push(Stack.Pop().Iter(this)); break; case InstructionType.IterableFull: Stack.Push(Stack.Pop().IterableFull(this)); break; case InstructionType.IterableNext: Stack.Push(Stack.Pop().IterableNext(this)); break; case InstructionType.Jump: pos = method.Labels[arg]; break; case InstructionType.JumpIfFalse: if (!Stack.Pop().ToBool(this).Bool) pos = method.Labels[arg]; break; case InstructionType.JumpIfTrue: if (Stack.Pop().ToBool(this).Bool) pos = method.Labels[arg]; break; case InstructionType.LoadAttribute: val = Stack.Pop(); try { var attribute = val.Attributes[CurrentModule.ConstantPool[arg]]; if (attribute.IsPrivate) { if (method.Parent != val) throw new InternalException(this, InternalException.ATTRIBUTE_ACCESS, CurrentModule.ConstantPool[arg], attribute.Parent.Type()); } if (attribute is HassiumProperty) Stack.Push(((HassiumProperty)attribute).Get.Invoke(this)); else Stack.Push(attribute); } catch (KeyNotFoundException) { throw new InternalException(this, InternalException.ATTRIBUTE_NOT_FOUND, CurrentModule.ConstantPool[arg], val.Type()); } break; case InstructionType.LoadGlobal: attrib = CurrentModule.ConstantPool[arg]; if (Globals.ContainsKey(attrib)) Stack.Push(Globals[attrib]); else if (method.Parent != null) { if (method.Parent.Attributes.ContainsKey(attrib)) Stack.Push(method.Parent.Attributes[attrib]); else throw new InternalException(this, InternalException.VARIABLE_ERROR, attrib); } else throw new InternalException(this, InternalException.VARIABLE_ERROR, attrib); break; case InstructionType.LoadGlobalVariable: try { Stack.Push(CurrentModule.Globals[arg]); } catch (KeyNotFoundException) { throw new InternalException(this, InternalException.VARIABLE_ERROR, arg); } break; case InstructionType.LoadListElement: list = Stack.Pop(); Stack.Push(list.Index(this, Stack.Pop())); break; case InstructionType.LoadLocal: Stack.Push(StackFrame.GetVariable(this, arg)); break; case InstructionType.Pop: Stack.Pop(); break; case InstructionType.PopHandler: Handlers.Pop(); break; case InstructionType.Push: Stack.Push(new HassiumInt(arg)); break; case InstructionType.PushConstant: Stack.Push(new HassiumString(CurrentModule.ConstantPool[arg])); break; case InstructionType.PushHandler: var handler = CurrentModule.ObjectPool[arg] as HassiumExceptionHandler; handler.Frame = StackFrame.Frames.Peek(); Handlers.Push(handler); break; case InstructionType.PushObject: Stack.Push(CurrentModule.ObjectPool[arg]); break; case InstructionType.Raise: RaiseException(Stack.Pop(), method, ref pos); break; case InstructionType.Reference: Stack.Push(new HassiumPointer(StackFrame.Frames.Peek(), arg)); break; case InstructionType.Return: return Stack.Pop(); case InstructionType.SelfReference: Stack.Push(method.Parent); break; case InstructionType.SetInitialAttribute: attrib = Stack.Pop().ToString(this).String; val = Stack.Pop(); var obj = Stack.Pop(); if (obj.Attributes.ContainsKey(attrib)) obj.Attributes.Remove(attrib); obj.Attributes.Add(attrib, val); Stack.Push(obj); break; case InstructionType.StoreAttribute: val = Stack.Pop(); attrib = CurrentModule.ConstantPool[arg]; try { if (val.Attributes.ContainsKey(attrib)) { if (val.Attributes[attrib] is HassiumProperty) { if (((HassiumProperty)val.Attributes[attrib]).Set == null) throw new InternalException(this, InternalException.ATTRIBUTE_NOT_FOUND, string.Format("set_{0}", attrib), val.Type()); ((HassiumProperty)val.Attributes[attrib]).Set.Invoke(this, Stack.Pop()); break; } else val.Attributes.Remove(attrib); } val.Attributes.Add(attrib, Stack.Pop()); } catch (KeyNotFoundException) { throw new InternalException(this, InternalException.VARIABLE_ERROR, val.Type()); } break; case InstructionType.StoreGlobalVariable: CurrentModule.Globals[arg] = Stack.Pop(); break; case InstructionType.StoreListElement: Stack.Push(Stack.Pop().StoreIndex(this, Stack.Pop(), Stack.Pop())); break; case InstructionType.StoreLocal: val = Stack.Pop(); if (StackFrame.Contains(arg)) StackFrame.Modify(arg, val); else StackFrame.Add(arg, val); break; case InstructionType.StoreReference: Stack.Push(((HassiumPointer)Stack.Pop()).StoreReference(Stack.Pop())); break; case InstructionType.Swap: int index = (int)Stack.Pop().ToInt(this).Int; val = StackFrame.GetVariable(this, index); StackFrame.Modify(index, StackFrame.GetVariable(this, arg)); StackFrame.Modify(arg, val); Stack.Push(val); break; case InstructionType.UnaryOperation: interpretUnaryOperation(Stack.Pop(), arg); break; } } catch (DivideByZeroException ex) { RaiseException(new HassiumString(ex.Message), method, ref pos); } catch (FileNotFoundException ex) { RaiseException(new HassiumString(ex.Message), method, ref pos); } catch (IOException ex) { RaiseException(new HassiumString(ex.Message), method, ref pos); } catch (InternalException ex) { RaiseException(new HassiumString(ex.Message), method, ref pos); } catch (Exception ex) { throw ex; RaiseException(new HassiumString(ex.Message), method, ref pos); } } return HassiumObject.Null; }
public HassiumClosure(HassiumMethod method, StackFrame.Frame frame) { Method = method; Frame = frame; AddType(TypeDefinition); }
private HassiumProperty compileProperty(PropertyNode node, HassiumClass parent) { var temp = method; method = new HassiumMethod(); method.Name = string.Format("get_{0}", node.Variable); method.IsPrivate = node.IsPrivate; method.SourceRepresentation = string.Format("{0} ()", method.Name); table.PushScope(); node.GetBody.Visit(this); table.PopScope(); HassiumMethod getBody = method; getBody.Parent = parent; getBody.ReturnType = ""; method = new HassiumMethod(); method.Name = string.Format("set_{0}", node.Variable); method.IsPrivate = node.IsPrivate; method.SourceRepresentation = string.Format("{0} (value)", method.Name); table.PushScope(); if (!table.ContainsSymbol("value")) table.AddSymbol("value"); method.Parameters.Add(new FuncParameter("value"), table.GetSymbol("value")); node.SetBody.Visit(this); table.PopScope(); HassiumMethod setBody = method; setBody.Parent = parent; setBody.ReturnType = ""; HassiumProperty property = new HassiumProperty(getBody, setBody); property.Parent = parent; method = temp; return property; }
public void RaiseException(HassiumObject message, HassiumMethod method, ref int pos) { if (Handlers.Count == 0) throw new InternalException(this, message.ToString(this).String); var handler = Handlers.Peek(); handler.Invoke(this, message); ExceptionReturns.Add(handler.Caller, handler.Caller.Labels[handler.Label]); }
private HassiumMethod compileFunc(FuncNode node) { if (!module.ConstantPool.ContainsKey(node.Name.GetHashCode())) module.ConstantPool.Add(node.Name.GetHashCode(), node.Name); method = new HassiumMethod(); method.Parent = new HassiumClass(); method.IsPrivate = node.IsPrivate; method.Name = node.Name; method.ReturnType = node.ReturnType; method.SourceRepresentation = node.GetSourceRepresentation(); table.PushScope(); foreach (var param in node.Parameters) method.Parameters.Add(param, table.AddSymbol(param.Name)); if (node.Children[0] is CodeBlockNode) node.Children[0].VisitChildren(this); else node.Children[0].Visit(this); table.PopScope(); return method; }
private HassiumMethod compileLambda(LambdaNode node) { var temp = method; method = new HassiumMethod(); method.Name = "lambda"; method.Parent = temp.Parent; table.PushScope(); foreach (AstNode param in node.Parameters.Children) { string name = ((IdentifierNode)param).Identifier; if (!table.ContainsSymbol(name)) table.AddSymbol(name); method.Parameters.Add(new FuncParameter(name), table.GetSymbol(name)); } node.Body.VisitChildren(this); table.PopScope(); var ret = method; method = temp; return ret; }
public HassiumModule Compile(AstNode ast, SymbolTable table) { this.table = table; module = new HassiumModule(); method = new HassiumMethod(); var globalParent = new HassiumClass(); foreach (AstNode child in ast.Children) { if (child is FuncNode) { compileFunc(child as FuncNode); method.Parent = new HassiumClass(); if (module.Attributes.ContainsKey(method.Name)) { if (module.Attributes[method.Name] is HassiumMultiFunc) ((HassiumMultiFunc)module.Attributes[method.Name]).Methods.Add(method); else if (module.Attributes[method.Name] is HassiumMethod) module.Attributes[method.Name] = new HassiumMultiFunc(new List<HassiumMethod>() { method, (HassiumMethod)module.Attributes[method.Name] }); } else module.Attributes.Add(method.Name, method); } else if (child is ClassNode) { var clazz = compileClass(child as ClassNode); clazz.Parent = globalParent; module.Attributes.Add(clazz.Name, clazz); } else if (child is ExpressionStatementNode) { if (child.Children[0] is BinaryOperationNode) { var binop = child.Children[0] as BinaryOperationNode; if (binop.BinaryOperation == BinaryOperation.Assignment) { string variable = ((IdentifierNode)binop.Left).Identifier; table.AddGlobalSymbol(variable); var temp = method; method = new HassiumMethod(); method.Name = variable; method.SourceRepresentation = string.Format("set_{0}", variable); binop.Right.Visit(this); method.Emit(child.SourceLocation, InstructionType.Return); module.InitialVariables.Add(table.GetGlobalSymbol(variable), method); method = temp; } } } else if (child is TraitNode || child is PropertyNode || child is UseNode || child is EnumNode) child.Visit(this); } preformInherits(module); return module; }
public void Accept(TryCatchNode node) { var endLabel = nextLabel(); var temp = method; method = new HassiumMethod(); method.Name = "catch"; table.PushScope(); if (!table.ContainsSymbol("value")) table.AddSymbol("value"); method.Parameters.Add(new FuncParameter("value"), table.GetSymbol("value")); node.CatchBody.VisitChildren(this); var handler = new HassiumExceptionHandler(temp, method, endLabel); if (!module.ObjectPool.ContainsKey(handler.GetHashCode())) module.ObjectPool.Add(handler.GetHashCode(), handler); method = temp; method.Emit(node.SourceLocation, InstructionType.PushHandler, handler.GetHashCode()); node.TryBody.Visit(this); method.Emit(node.SourceLocation, InstructionType.PopHandler); method.EmitLabel(node.SourceLocation, endLabel); }
public void Accept(ThreadNode node) { var temp = method; method = new HassiumMethod(); method.Name = "thread"; node.Body.Visit(this); if (!module.ObjectPool.ContainsKey(method.GetHashCode())) module.ObjectPool.Add(method.GetHashCode(), method); temp.Emit(node.SourceLocation, InstructionType.BuildThread, method.GetHashCode()); if (node.RunImmediately) { int hash = "start".GetHashCode(); if (!module.ConstantPool.ContainsKey(hash)) module.ConstantPool.Add(hash, "start"); temp.Emit(node.SourceLocation, InstructionType.LoadAttribute, hash); temp.Emit(node.SourceLocation, InstructionType.Call); } method = temp; }
public void Accept(FuncNode node) { var temp = method; compileFunc(node); if (!module.ObjectPool.ContainsKey(method.GetHashCode())) module.ObjectPool.Add(method.GetHashCode(), method); if (!table.ContainsSymbol(method.Name)) table.AddSymbol(method.Name); temp.Emit(node.SourceLocation, InstructionType.PushObject, method.GetHashCode()); temp.Emit(node.SourceLocation, InstructionType.StoreLocal, table.GetSymbol(method.Name)); method = temp; }
public void Accept(ClassNode node) { var temp = method; var clazz = compileClass(node); if (!module.ObjectPool.ContainsKey(clazz.GetHashCode())) module.ObjectPool.Add(clazz.GetHashCode(), clazz); temp.Emit(node.SourceLocation, InstructionType.PushObject, clazz.GetHashCode()); if (!table.ContainsSymbol(node.Name)) table.AddSymbol(node.Name); temp.Emit(node.SourceLocation, InstructionType.StoreLocal, table.GetSymbol(node.Name)); method = temp; }