diff --git a/src/Hassium/Compiler/CodeGen/Compiler.cs b/src/Hassium/Compiler/CodeGen/Compiler.cs
index 8159ec4..add04ad 100644
--- a/src/Hassium/Compiler/CodeGen/Compiler.cs
+++ b/src/Hassium/Compiler/CodeGen/Compiler.cs
@@ -529,6 +529,17 @@ public void Accept(TernaryOperationNode node)
node.FalseStatement.Visit(this);
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());
+ method = temp;
+ }
public void Accept(TraitNode node)
{
int hash = node.Name.GetHashCode();
diff --git a/src/Hassium/Compiler/CodeGen/InstructionType.cs b/src/Hassium/Compiler/CodeGen/InstructionType.cs
index e8ffb41..921db9e 100644
--- a/src/Hassium/Compiler/CodeGen/InstructionType.cs
+++ b/src/Hassium/Compiler/CodeGen/InstructionType.cs
@@ -9,6 +9,7 @@ public enum InstructionType
BuildDictionary,
BuildKeyValuePair,
BuildList,
+ BuildThread,
BuildTuple,
Call,
Dereference,
diff --git a/src/Hassium/Compiler/Parser/Ast/ThreadNode.cs b/src/Hassium/Compiler/Parser/Ast/ThreadNode.cs
new file mode 100644
index 0000000..5048817
--- /dev/null
+++ b/src/Hassium/Compiler/Parser/Ast/ThreadNode.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Hassium.Compiler.Parser.Ast
+{
+ public class ThreadNode: AstNode
+ {
+ public AstNode Body { get { return Children[0]; } }
+
+ public ThreadNode(SourceLocation location, AstNode body)
+ {
+ this.SourceLocation = location;
+ Children.Add(body);
+ }
+
+ public override void Visit(IVisitor visitor)
+ {
+ visitor.Accept(this);
+ }
+ public override void VisitChildren(IVisitor visitor)
+ {
+ foreach (AstNode child in Children)
+ child.Visit(visitor);
+ }
+ }
+}
+
diff --git a/src/Hassium/Compiler/Parser/IVisitor.cs b/src/Hassium/Compiler/Parser/IVisitor.cs
index 742e3ed..7762a3c 100644
--- a/src/Hassium/Compiler/Parser/IVisitor.cs
+++ b/src/Hassium/Compiler/Parser/IVisitor.cs
@@ -39,6 +39,7 @@ public interface IVisitor
void Accept(StringNode node);
void Accept(SwitchNode node);
void Accept(TernaryOperationNode node);
+ void Accept(ThreadNode node);
void Accept(TraitNode node);
void Accept(TryCatchNode node);
void Accept(TupleNode node);
diff --git a/src/Hassium/Compiler/Parser/Parser.cs b/src/Hassium/Compiler/Parser/Parser.cs
index a264ca6..55461d1 100644
--- a/src/Hassium/Compiler/Parser/Parser.cs
+++ b/src/Hassium/Compiler/Parser/Parser.cs
@@ -82,7 +82,7 @@ private AstNode parseStatement()
block.Children.Add(parseStatement());
return block;
}
- else if (MatchToken(TokenType.Identifier) && Tokens[Position + 1].TokenType == TokenType.OpenBracket)
+ else if (MatchToken(TokenType.Identifier) && !MatchToken(TokenType.Identifier, "thread") && Tokens[Position + 1].TokenType == TokenType.OpenBracket)
return parseProperty();
else if (MatchToken(TokenType.Identifier) && Tokens[Position + 1].TokenType == TokenType.Identifier)
return parseEnforcedAssignment();
@@ -621,6 +621,8 @@ private AstNode parseTerm()
return parseExpression();
else if (MatchToken(TokenType.Identifier, "lambda"))
return parseLambda();
+ else if (AcceptToken(TokenType.Identifier, "thread"))
+ return new ThreadNode(Location, parseStatement());
else if (MatchToken(TokenType.OpenSquare))
return parseListDeclaration();
else if (AcceptToken(TokenType.OpenBracket))
diff --git a/src/Hassium/Compiler/SemanticAnalysis/SemanticAnalyzer.cs b/src/Hassium/Compiler/SemanticAnalysis/SemanticAnalyzer.cs
index 5946d45..f08366f 100644
--- a/src/Hassium/Compiler/SemanticAnalysis/SemanticAnalyzer.cs
+++ b/src/Hassium/Compiler/SemanticAnalysis/SemanticAnalyzer.cs
@@ -66,6 +66,7 @@ public void Accept(StatementNode node) {}
public void Accept(StringNode node) {}
public void Accept(SwitchNode node) {}
public void Accept(TernaryOperationNode node) {}
+ public void Accept(ThreadNode node) {}
public void Accept(TraitNode node) {}
public void Accept(TryCatchNode node) {}
public void Accept(TupleNode node) {}
diff --git a/src/Hassium/Hassium.csproj b/src/Hassium/Hassium.csproj
index 4ccf055..d484991 100644
--- a/src/Hassium/Hassium.csproj
+++ b/src/Hassium/Hassium.csproj
@@ -154,6 +154,9 @@
+
+
+
diff --git a/src/Hassium/Runtime/Objects/HassiumMethod.cs b/src/Hassium/Runtime/Objects/HassiumMethod.cs
index 1574df7..72f5cc2 100644
--- a/src/Hassium/Runtime/Objects/HassiumMethod.cs
+++ b/src/Hassium/Runtime/Objects/HassiumMethod.cs
@@ -48,46 +48,64 @@ public void EmitLabel(SourceLocation location, int label)
// Instructions.Add(new Instruction(location, InstructionType.Label, label));
}
+ public HassiumObject Invoke(VirtualMachine vm, StackFrame.Frame frame)
+ {
+ vm.StackFrame.Frames.Push(frame);
+ return Invoke(vm);
+ }
+
public override HassiumObject Invoke(VirtualMachine vm, params HassiumObject[] args)
{
- if (Name != "lambda" && Name != "catch") vm.StackFrame.PushFrame();
- vm.CallStack.Push(SourceRepresentation);
- int i = 0;
- foreach (var param in Parameters)
- {
- var arg = args[i++];
- if (param.Key.IsEnforced)
- if (!arg.Types.Contains((HassiumTypeDefinition)vm.Globals[param.Key.Type].Type()))
- throw new InternalException(vm, InternalException.PARAMETER_ERROR, param.Key.Type, arg.Type());
- vm.StackFrame.Add(param.Value, arg);
- }
- if (IsConstructor)
- {
- HassiumClass ret = new HassiumClass();
- ret.Attributes = CloneDictionary(Parent.Attributes);
- foreach (var type in Parent.Types)
- ret.AddType(type);
- foreach (var attrib in ret.Attributes.Values)
- attrib.Parent = ret;
- vm.ExecuteMethod(ret.Attributes["new"] as HassiumMethod);
- vm.StackFrame.PopFrame();
- vm.CallStack.Pop();
- return ret;
- }
- else
+ try
{
- var val = vm.ExecuteMethod(this);
- if (Name == "catch")
+ if (Name != "lambda" && Name != "catch" && Name != "thread") vm.StackFrame.PushFrame();
+ vm.CallStack.Push(SourceRepresentation);
+ int i = 0;
+ foreach (var param in Parameters)
{
+ var arg = args[i++];
+ if (param.Key.IsEnforced)
+ if (!arg.Types.Contains((HassiumTypeDefinition)vm.Globals[param.Key.Type].Type()))
+ throw new InternalException(vm, InternalException.PARAMETER_ERROR, param.Key.Type, arg.Type());
+ vm.StackFrame.Add(param.Value, arg);
+ }
+ if (IsConstructor)
+ {
+ HassiumClass ret = new HassiumClass();
+ ret.Attributes = CloneDictionary(Parent.Attributes);
+ foreach (var type in Parent.Types)
+ ret.AddType(type);
+ foreach (var attrib in ret.Attributes.Values)
+ attrib.Parent = ret;
+ vm.ExecuteMethod(ret.Attributes["new"] as HassiumMethod);
+ vm.StackFrame.PopFrame();
+ vm.CallStack.Pop();
+ return ret;
+ }
+ else
+ {
+ var val = vm.ExecuteMethod(this);
+ if (Name == "catch")
+ {
+ vm.CallStack.Pop();
+ return val;
+ }
+ if (ReturnType != "" && ReturnType != null)
+ if (val.Type() != vm.Globals[ReturnType])
+ throw new InternalException(vm, InternalException.RETURN_ERROR, ReturnType, val.Type());
+ if (Name != "lambda") vm.StackFrame.PopFrame();
vm.CallStack.Pop();
return val;
}
- if (ReturnType != "" && ReturnType != null)
- if (val.Type() != vm.Globals[ReturnType])
- throw new InternalException(vm, InternalException.RETURN_ERROR, ReturnType, val.Type());
- if (Name != "lambda") vm.StackFrame.PopFrame();
- vm.CallStack.Pop();
- return val;
+ }
+ catch (InternalException ex)
+ {
+ Console.WriteLine("At location {0}:", ex.VM.CurrentSourceLocation);
+ Console.WriteLine("{0} at:", ex.Message);
+ while (ex.VM.CallStack.Count > 0)
+ Console.WriteLine(ex.VM.CallStack.Pop());
+ Environment.Exit(0);
+ return null;
}
}
diff --git a/src/Hassium/Runtime/Objects/Types/HassiumThread.cs b/src/Hassium/Runtime/Objects/Types/HassiumThread.cs
new file mode 100644
index 0000000..3a73e4d
--- /dev/null
+++ b/src/Hassium/Runtime/Objects/Types/HassiumThread.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Hassium.Runtime.Objects.Types
+{
+ public class HassiumThread: HassiumObject
+ {
+ public static new HassiumTypeDefinition TypeDefinition = new HassiumTypeDefinition("thread");
+
+ public Thread Thread { get; private set; }
+
+ public HassiumThread(VirtualMachine vm, HassiumMethod method, StackFrame.Frame frame)
+ {
+ VirtualMachine newVM = vm.Clone() as VirtualMachine;
+ newVM.ExceptionReturns = new Dictionary();
+ newVM.Handlers = new Stack();
+ newVM.Stack = new Stack();
+ newVM.StackFrame = new StackFrame();
+ Thread = new Thread(() => method.Invoke(newVM, frame));
+
+ AddType(TypeDefinition);
+ AddAttribute("isAlive", new HassiumProperty(get_isAlive));
+ AddAttribute("start", start, 0);
+ AddAttribute("stop", stop, 0);
+ }
+
+ public HassiumBool get_isAlive(VirtualMachine vm, params HassiumObject[] args)
+ {
+ return new HassiumBool(Thread.IsAlive);
+ }
+ public HassiumNull start(VirtualMachine vm, params HassiumObject[] args)
+ {
+ Thread.Start();
+ return HassiumObject.Null;
+ }
+ public HassiumNull stop(VirtualMachine vm, params HassiumObject[] args)
+ {
+ Thread.Abort();
+ return HassiumObject.Null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Hassium/Runtime/Objects/Types/HassiumTypesModule.cs b/src/Hassium/Runtime/Objects/Types/HassiumTypesModule.cs
index 61e6fbe..3a1ffd9 100644
--- a/src/Hassium/Runtime/Objects/Types/HassiumTypesModule.cs
+++ b/src/Hassium/Runtime/Objects/Types/HassiumTypesModule.cs
@@ -17,10 +17,11 @@ public HassiumTypesModule() : base("types")
AddAttribute("keyValuePair", HassiumKeyValuePair.TypeDefinition);
AddAttribute("int", HassiumInt.TypeDefinition);
AddAttribute("list", HassiumList.TypeDefinition);
+ AddAttribute("null", HassiumObject.Null);
AddAttribute("object", HassiumObject.TypeDefinition);
AddAttribute("property", HassiumProperty.TypeDefinition);
- AddAttribute("null", HassiumObject.Null);
AddAttribute("string", HassiumString.TypeDefinition);
+ AddAttribute("thread", HassiumThread.TypeDefinition);
AddAttribute("trait", HassiumTrait.TypeDefinition);
AddAttribute("TypeDefinition", HassiumTypeDefinition.TypeDefinition);
}
diff --git a/src/Hassium/Runtime/StackFrame.cs b/src/Hassium/Runtime/StackFrame.cs
index 40bf865..acc0f3c 100644
--- a/src/Hassium/Runtime/StackFrame.cs
+++ b/src/Hassium/Runtime/StackFrame.cs
@@ -7,7 +7,7 @@ namespace Hassium.Runtime
{
public class StackFrame
{
- public class Frame
+ public class Frame : ICloneable
{
public Dictionary variables = new Dictionary();
public void Add(int index, HassiumObject value)
@@ -26,6 +26,10 @@ public HassiumObject GetVariable(int index)
{
return variables[index];
}
+ public object Clone()
+ {
+ return this.MemberwiseClone();
+ }
}
public Stack Frames;
public Dictionary Locals { get { return Frames.Peek().variables; } }
diff --git a/src/Hassium/Runtime/VirtualMachine.cs b/src/Hassium/Runtime/VirtualMachine.cs
index 09113e0..8e1145e 100644
--- a/src/Hassium/Runtime/VirtualMachine.cs
+++ b/src/Hassium/Runtime/VirtualMachine.cs
@@ -10,17 +10,17 @@
namespace Hassium.Runtime
{
- public class VirtualMachine
+ public class VirtualMachine : ICloneable
{
public Stack CallStack { get; private set; }
public HassiumMethod CurrentMethod { get; private set; }
public HassiumModule CurrentModule { get; private set; }
public SourceLocation CurrentSourceLocation { get; private set; }
- public Dictionary ExceptionReturns { get; private set; }
+ public Dictionary ExceptionReturns { get; set; }
public Dictionary Globals { get; private set; }
- public Stack Handlers { get; private set; }
- public Stack Stack { get; private set; }
- public StackFrame StackFrame { get; private set; }
+ public Stack Handlers { get; set; }
+ public Stack Stack { get; set; }
+ public StackFrame StackFrame { get; set; }
public void Execute(HassiumModule module, string[] args)
{
@@ -86,6 +86,9 @@ public HassiumObject ExecuteMethod(HassiumMethod method)
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++)
@@ -420,5 +423,10 @@ private void importInitials()
foreach (var pair in CurrentModule.InitialVariables)
CurrentModule.Globals.Add(pair.Key, pair.Value.Invoke(this));
}
+
+ public object Clone()
+ {
+ return this.MemberwiseClone();
+ }
}
}
\ No newline at end of file
diff --git a/src/Hassium/Runtime/VirtualMachineContext.cs b/src/Hassium/Runtime/VirtualMachineContext.cs
new file mode 100644
index 0000000..71ce56d
--- /dev/null
+++ b/src/Hassium/Runtime/VirtualMachineContext.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+
+namespace Hassium.Runtime
+{
+ public class VirtualMachineContext
+ {
+ public VirtualMachineContext()
+ {
+ }
+ }
+}
+