changeset 6:a6329b092499

Added scopes, function builder
author cin
date Wed, 30 Oct 2013 17:38:35 +0400
parents cb13da6e3349
children 5b2302d3ac4f
files Jint.Runtime/Jint.Runtime.csproj Jint.Runtime/VM/AbstractBox.cs Jint.Runtime/VM/Box.cs Jint.Runtime/VM/Frame.cs Jint.Runtime/VM/FunctionBuilder.cs Jint.Runtime/VM/IReference.cs Jint.Runtime/VM/Machine.cs Jint.Runtime/VM/OpCodes/BinaryOp.cs Jint.Runtime/VM/Scope.cs Jint.Runtime/VM/ScopeReference.cs Jint.userprefs
diffstat 11 files changed, 403 insertions(+), 233 deletions(-) [+]
line wrap: on
line diff
--- a/Jint.Runtime/Jint.Runtime.csproj	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.Runtime/Jint.Runtime.csproj	Wed Oct 30 17:38:35 2013 +0400
@@ -50,6 +50,10 @@
     <Compile Include="VM\OpCodes\GteCmp.cs" />
     <Compile Include="VM\OperationDelegates.cs" />
     <Compile Include="VM\RuntimeContext.cs" />
+    <Compile Include="VM\Scope.cs" />
+    <Compile Include="VM\ScopeReference.cs" />
+    <Compile Include="VM\IReference.cs" />
+    <Compile Include="VM\FunctionBuilder.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
@@ -60,4 +64,7 @@
     </MonoDevelop>
   </ProjectExtensions>
   <ItemGroup />
+  <ItemGroup>
+    <Folder Include="VM\" />
+  </ItemGroup>
 </Project>
\ No newline at end of file
--- a/Jint.Runtime/VM/AbstractBox.cs	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.Runtime/VM/AbstractBox.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -1,23 +1,24 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Jint.Runtime.VM {
-    using OpCodes;
-
-    abstract class AbstractBox {
-
-        protected AbstractBox(Type type) {
-            holdingType = type;
-        }
-
-        public readonly Type holdingType;
-
-        public abstract void InvokeBinaryOperation(Codes code, int arg2, int dest, Frame frame);
-        public abstract void InvokeUnaryOperation(Codes code, int dest, Frame frame);
-        public abstract int InvokeCompareOperation(int arg2, Frame frame);
-        public abstract bool InvokeEqualityOperation(int arg2, Frame frame);
-        public abstract T Convert<T>();
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM {
+    using OpCodes;
+
+    abstract class AbstractBox {
+
+        protected AbstractBox(Type type) {
+            holdingType = type;
+        }
+
+        public readonly Type holdingType;
+
+        public abstract void InvokeBinaryOperation(Codes code, int arg2, int dest, Frame frame);
+        public abstract void InvokeUnaryOperation(Codes code, int dest, Frame frame);
+        public abstract int InvokeCompareOperation(int arg2, Frame frame);
+        public abstract bool InvokeEqualityOperation(int arg2, Frame frame);
+        public abstract T Convert<T>();
+		public abstract void CopyTo (Frame frame, int dest);
+    }
+}
--- a/Jint.Runtime/VM/Box.cs	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.Runtime/VM/Box.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -1,72 +1,77 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Jint.Runtime.VM.OpCodes;
-using System.ComponentModel;
-
-namespace Jint.Runtime.VM {
-    class Box<T>: AbstractBox, IGettter<T>, ISetter<T> {
-
-        public T holdingValue;
-        object[] m_impl;
-        RuntimeContext m_runtime;
-        TypeConverter m_converter;
-
-        public Box(T value, RuntimeContext runtime): base(typeof(T)) {
-            if (runtime == null)
-                throw new ArgumentNullException("runtime");
-
-            holdingValue = value;
-            m_runtime = runtime;
-        }
-
-        object[] Impl {
-            get {
-                if (m_impl == null)
-                    m_impl = m_runtime.GetImpl(typeof(T));
-                return m_impl;
-            }
-        }
-
-        TypeConverter TypeConverter {
-            get {
-                if (m_converter == null)
-                    m_converter = TypeDescriptor.GetConverter(typeof(T));
-                return m_converter;
-            }
-        }
-
-        public T Get() {
-            return holdingValue;
-        }
-
-        public void Set(T value) {
-            holdingValue = value;
-        }
-
-        public override void InvokeBinaryOperation(Codes code, int arg2, int dest, Frame frame) {
-            var op = (BinaryOperation<T>)Impl[(int)code];
-            frame.SetValue(dest, op(holdingValue, frame.GetValue<T>(arg2)));
-        }
-
-        public override void InvokeUnaryOperation(Codes code, int dest, Frame frame) {
-            var op = (UnaryOperation<T>)Impl[(int)code];
-            frame.SetValue(dest, op(holdingValue));
-        }
-
-        public override int InvokeCompareOperation(int arg2, Frame frame) {
-            var op = (CompareOperation<T>)Impl[(int)Codes.Cmp];
-            return op(holdingValue, frame.GetValue<T>(arg2));
-        }
-
-        public override bool InvokeEqualityOperation(int arg2, Frame frame) {
-            var op = (EqualityOperation<T>)Impl[(int)Codes.Cmp];
-            return op(holdingValue, frame.GetValue<T>(arg2));
-        }
-
-        public override T2 Convert<T2>() {
-            return (T2)TypeConverter.ConvertTo(holdingValue, typeof(T2));
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Jint.Runtime.VM.OpCodes;
+using System.ComponentModel;
+
+namespace Jint.Runtime.VM {
+    class Box<T>: AbstractBox, IGettter<T>, ISetter<T> {
+
+        public T holdingValue;
+        object[] m_impl;
+        RuntimeContext m_runtime;
+        TypeConverter m_converter;
+
+        public Box(T value, RuntimeContext runtime): base(typeof(T)) {
+            if (runtime == null)
+                throw new ArgumentNullException("runtime");
+
+            holdingValue = value;
+            m_runtime = runtime;
+        }
+
+        object[] Impl {
+            get {
+                if (m_impl == null)
+                    m_impl = m_runtime.GetImpl(typeof(T));
+                return m_impl;
+            }
+        }
+
+        TypeConverter TypeConverter {
+            get {
+                if (m_converter == null)
+                    m_converter = TypeDescriptor.GetConverter(typeof(T));
+                return m_converter;
+            }
+        }
+
+        public T Get() {
+            return holdingValue;
+        }
+
+        public void Set(T value) {
+            holdingValue = value;
+        }
+
+        public override void InvokeBinaryOperation(Codes code, int arg2, int dest, Frame frame) {
+            var op = (BinaryOperation<T>)Impl[(int)code];
+            frame.SetValue(dest, op(holdingValue, frame.GetValue<T>(arg2)));
+        }
+
+        public override void InvokeUnaryOperation(Codes code, int dest, Frame frame) {
+            var op = (UnaryOperation<T>)Impl[(int)code];
+            frame.SetValue(dest, op(holdingValue));
+        }
+
+        public override int InvokeCompareOperation(int arg2, Frame frame) {
+            var op = (CompareOperation<T>)Impl[(int)Codes.Cmp];
+            return op(holdingValue, frame.GetValue<T>(arg2));
+        }
+
+        public override bool InvokeEqualityOperation(int arg2, Frame frame) {
+            var op = (EqualityOperation<T>)Impl[(int)Codes.Cmp];
+            return op(holdingValue, frame.GetValue<T>(arg2));
+        }
+
+        public override T2 Convert<T2>() {
+            return (T2)TypeConverter.ConvertTo(holdingValue, typeof(T2));
+        }
+
+		public override void CopyTo (Frame frame, int dest)
+		{
+			frame.SetValue (dest, holdingValue);
+		}
+    }
+}
--- a/Jint.Runtime/VM/Frame.cs	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.Runtime/VM/Frame.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -1,73 +1,77 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Jint.Runtime.VM {
-    class Frame {
-        AbstractBox[] m_registers;
-        RuntimeContext m_runtime;
-
-        public Frame(int size, RuntimeContext runtime) {
-            if (runtime == null)
-                throw new ArgumentNullException("runtime");
-            if (size < 0)
-                throw new ArgumentOutOfRangeException("size");
-            m_runtime = runtime;
-            m_registers = new AbstractBox[size];
-        }
-
-        /// <summary>
-        /// Return register at the specified index.
-        /// </summary>
-        /// <param name="index">The index of the register</param>
-        /// <returns>The register.</returns>
-        public AbstractBox this[int index] {
-            get {
-                return m_registers[index];
-            }
-            set {
-                m_registers[index] = value;
-            }
-        }
-
-        /// <summary>
-        /// Extracts value stored in the register specified by the index.
-        /// </summary>
-        /// <remarks>This method doesn't do any cast, if the specified type isn't the same as the type of the stored value a type cast exception will occur.</remarks>
-        /// <typeparam name="T">The type of the value stored in the register.</typeparam>
-        /// <param name="index">The index of the register.</param>
-        /// <returns>The value stored in the register.</returns>
-        public T GetValue<T>(int index) {
-            return ((Box<T>)m_registers[index]).holdingValue;
-        }
-
-        /// <summary>
-        /// Stores a new value in the register specified by the index.
-        /// </summary>
-        /// <remarks>
-        /// If the previous value has the same type as the value being stored in the register,
-        /// the new value will replace the old one, otherwise the register will be reallocated to
-        /// store the new value.
-        /// </remarks>
-        /// <typeparam name="T">The type of the value being stored</typeparam>
-        /// <param name="index">The index of the register where the value will be stored</param>
-        /// <param name="value">The value to be stored in the register</param>
-        public void SetValue<T>(int index, T value) {
-            var reg = m_registers[index] as Box<T>;
-            if (reg == null || reg.holdingType != typeof(T))
-                m_registers[index] = m_runtime.BoxValue(value);
-            else
-                reg.holdingValue = value;
-        }
-
-        public T GetConverted<T>(int index) {
-            var reg = m_registers[index];
-
-            if (reg.holdingType == typeof(T))
-                return ((Box<T>)reg).holdingValue;
-            else
-                return reg.Convert<T>();
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM {
+    class Frame {
+        AbstractBox[] m_registers;
+        RuntimeContext m_runtime;
+
+		public const int ThisRegister = 0;
+		public const int ScopeRegister = 1;
+		public const int FirstVarRegsiter = 2;
+
+        public Frame(int size, RuntimeContext runtime) {
+            if (runtime == null)
+                throw new ArgumentNullException("runtime");
+            if (size < 0)
+                throw new ArgumentOutOfRangeException("size");
+            m_runtime = runtime;
+            m_registers = new AbstractBox[size];
+        }
+
+        /// <summary>
+        /// Return register at the specified index.
+        /// </summary>
+        /// <param name="index">The index of the register</param>
+        /// <returns>The register.</returns>
+        public AbstractBox this[int index] {
+            get {
+                return m_registers[index];
+            }
+            set {
+                m_registers[index] = value;
+            }
+        }
+
+        /// <summary>
+        /// Extracts value stored in the register specified by the index.
+        /// </summary>
+        /// <remarks>This method doesn't do any cast, if the specified type isn't the same as the type of the stored value a type cast exception will occur.</remarks>
+        /// <typeparam name="T">The type of the value stored in the register.</typeparam>
+        /// <param name="index">The index of the register.</param>
+        /// <returns>The value stored in the register.</returns>
+        public T GetValue<T>(int index) {
+            return ((Box<T>)m_registers[index]).holdingValue;
+        }
+
+        /// <summary>
+        /// Stores a new value in the register specified by the index.
+        /// </summary>
+        /// <remarks>
+        /// If the previous value has the same type as the value being stored in the register,
+        /// the new value will replace the old one, otherwise the register will be reallocated to
+        /// store the new value.
+        /// </remarks>
+        /// <typeparam name="T">The type of the value being stored</typeparam>
+        /// <param name="index">The index of the register where the value will be stored</param>
+        /// <param name="value">The value to be stored in the register</param>
+        public void SetValue<T>(int index, T value) {
+            var reg = m_registers[index] as Box<T>;
+            if (reg == null || reg.holdingType != typeof(T))
+                m_registers[index] = m_runtime.BoxValue(value);
+            else
+                reg.holdingValue = value;
+        }
+
+        public T GetConverted<T>(int index) {
+            var reg = m_registers[index];
+
+            if (reg.holdingType == typeof(T))
+                return ((Box<T>)reg).holdingValue;
+            else
+                return reg.Convert<T>();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/FunctionBuilder.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+
+namespace Jint.Runtime.VM
+{
+	class FunctionBuidler
+	{
+		Scope m_parentScope;
+
+		/// <summary>
+		/// maps local variable names to the registers
+		/// </summary>
+		Dictionary<string,int> m_locals;
+
+		/// <summary>
+		/// maps formal parameters to local variables
+		/// </summary>
+		int[] m_formalParameters;
+
+		int m_frameSize;
+
+		IInstruction m_code;
+
+		RuntimeContext m_runtime;
+
+		public FunctionBuilder (string[] argumentNames, RuntimeContext runtime, Scope parentScope)
+		{
+			m_parentScope;
+			m_frameSize = 2; // reserve for this and scope
+
+			m_locals = new Dictionary<string,int>();
+
+			if (argumentNames!= null) {
+				m_formalParameters = new int[argumentNames.Length];
+				for(int i = 0; i < argumentNames.Length; i++)
+					m_formalParameters[i] = AllocVariable(argumentNames[i]);
+			}
+		}
+
+		// all vars should be allocated before temp registers
+		public int AllocVariable(string name) {
+			int id;
+
+			if (m_locals.TryGetValue (name, out id))
+				return id;
+
+			id = m_frameSize++;
+			m_locals [name] = id;
+			return id;
+		}
+
+		public int AllocateRegister() {
+			return m_frameSize++;
+		}
+
+		public void Invoke (object that, object[] args) {
+			var frame = new Frame (m_frameSize, m_runtime);
+			var scope = new Scope (m_locals, frame, m_declaringScope);
+			frame.SetValue (Frame.ThisRegister, that);
+			frame.SetValue (Frame.ScopeRegister, scope);
+
+			var paramLen = Math.Min (m_formalParameters.Length, args.Length);
+
+			for (int i=0; i< paramLen; i++)
+				frame.SetValue (m_formalParameters [i], args [i]);
+		}
+
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/IReference.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -0,0 +1,12 @@
+using System;
+
+namespace Jint.Runtime.VM
+{
+	interface IReference
+	{
+		T Get<T>();
+		void Put<T>(T value);
+		void CopyTo (Frame frame, int dest);
+	}
+}
+
--- a/Jint.Runtime/VM/Machine.cs	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.Runtime/VM/Machine.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -1,15 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Jint.Runtime.VM {
-    class Machine {
-        Frame m_frame;
-
-        public void Run(IInstruction prog) {
-            while (prog != null)
-                prog = prog.Invoke(m_frame);
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM {
+    class Machine {
+        Frame m_frame;
+
+        public void Run(IInstruction prog) {
+            while (prog != null)
+                prog = prog.Invoke(m_frame);
+        }
+    }
+}
--- a/Jint.Runtime/VM/OpCodes/BinaryOp.cs	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.Runtime/VM/OpCodes/BinaryOp.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -1,36 +1,36 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Jint.Runtime.VM.OpCodes {
-    delegate void BinaryInstructionImpl(int arg1, int arg2, int dest, Frame frame);
-
-    class BinaryOp: IInstruction {
-
-        int m_dest;
-        int m_arg1;
-        int m_arg2;
-        Codes m_code;
-        IInstruction m_next;
-
-        public BinaryOp(Codes code, int arg1, int arg2, int dest) {
-            m_code = code;
-            m_arg1 = arg1;
-            m_arg2 = arg2;
-            m_dest = dest;
-        }
-
-        public IInstruction Chain(IInstruction next) {
-            m_next = next;
-            return next;
-        }
-
-        public IInstruction Invoke(Frame frame) {
-            //frame[m_arg1].GetBinaryImpl(m_code)(m_arg1, m_arg2, m_dest, frame);
-            frame[m_arg1].InvokeBinaryOperation(m_code, m_arg2, m_dest, frame);
-
-            return m_next;
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Jint.Runtime.VM.OpCodes {
+    delegate void BinaryInstructionImpl(int arg1, int arg2, int dest, Frame frame);
+
+    class BinaryOp: IInstruction {
+
+        int m_dest;
+        int m_arg1;
+        int m_arg2;
+        Codes m_code;
+        IInstruction m_next;
+
+        public BinaryOp(Codes code, int arg1, int arg2, int dest) {
+            m_code = code;
+            m_arg1 = arg1;
+            m_arg2 = arg2;
+            m_dest = dest;
+        }
+
+        public IInstruction Chain(IInstruction next) {
+            m_next = next;
+            return next;
+        }
+
+        public IInstruction Invoke(Frame frame) {
+            //frame[m_arg1].GetBinaryImpl(m_code)(m_arg1, m_arg2, m_dest, frame);
+            frame[m_arg1].InvokeBinaryOperation(m_code, m_arg2, m_dest, frame);
+
+            return m_next;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/Scope.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+
+namespace Jint.Runtime.VM
+{
+	class Scope
+	{
+		Frame m_frame;
+		Dictionary<string,int> m_vars;
+		Scope m_parent;
+
+		public const int ThisRegister = 0;
+		public const int ScopeRegister = 1;
+		public const int FirstVarRegsiter = 2;
+
+		public Scope (IDictionary<string,int> vars, Frame frame, Scope parent)
+		{
+			if (vars == null)
+				throw new ArgumentNullException ("vars");
+			if (frame == null)
+				throw new ArgumentNullException ("frame");
+
+			m_vars = new Dictionary<string, int> (vars);
+			m_frame = frame;
+			m_parent = parent;
+		}
+
+		public IReference Resolve(string name) {
+			if (String.IsNullOrEmpty (name))
+				throw new ArgumentException ("The specified variable name is invalid");
+
+			int index; 
+			if (m_vars.TryGetValue (name, out index))
+				return new ScopeReference (this, index);
+
+			if (m_parent != null)
+				return m_parent.Resolve (name);
+			else
+				throw new KeyNotFoundException (String.Format("The specified variable '{0}' isn't found",name));
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jint.Runtime/VM/ScopeReference.cs	Wed Oct 30 17:38:35 2013 +0400
@@ -0,0 +1,35 @@
+using System;
+
+namespace Jint.Runtime.VM
+{
+	public class ScopeReference: IReference
+	{
+		Frame m_frame;
+		int m_index;
+		public ScopeReference (Frame frame, int index)
+		{
+			if (frame == null)
+				throw new ArgumentNullException("frame");
+
+			m_index = index;
+			m_frame = frame;
+		}
+
+
+		#region IReference implementation
+		public T Get<T> ()
+		{
+			return m_frame.GetValue<T>(m_index);
+		}
+		public void Put<T> (T value)
+		{
+			m_frame.SetValue(m_index);
+		}
+		public void CopyTo (Frame frame, int dest)
+		{
+			m_frame[m_index].CopyTo(frame,dest);
+		}
+		#endregion
+	}
+}
+
--- a/Jint.userprefs	Mon Oct 28 00:49:15 2013 +0400
+++ b/Jint.userprefs	Wed Oct 30 17:38:35 2013 +0400
@@ -1,16 +1,12 @@
 <Properties>
   <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug|x86" />
-  <MonoDevelop.Ide.Workbench ActiveDocument="Jint.Runtime/Main.cs">
+  <MonoDevelop.Ide.Workbench ActiveDocument="Jint.Runtime/VM/Frame.cs">
     <Files>
-      <File FileName="Jint.Runtime/VM/OpCodes/IBinaryOperation2.cs" Line="1" Column="1" />
-      <File FileName="Jint.Runtime/VM2/OpCodes/Codes.cs" Line="13" Column="1" />
-      <File FileName="Jint.Runtime/VM2/Box.cs" Line="15" Column="4" />
-      <File FileName="Jint.Runtime/VM2/IntegerBinder.cs" Line="1" Column="1" />
-      <File FileName="Jint.Runtime/VM2/Instruction.cs" Line="1" Column="1" />
-      <File FileName="Jint.Runtime/VM2/OpCodes/Operation.cs" Line="4" Column="50" />
-      <File FileName="Jint.Runtime/VM2/Machine.cs" Line="33" Column="16" />
-      <File FileName="Jint.Runtime/VM2/RuntimeContext.cs" Line="20" Column="3" />
-      <File FileName="Jint.Runtime/Main.cs" Line="34" Column="30" />
+      <File FileName="Jint.Runtime/Main.cs" Line="32" Column="15" />
+      <File FileName="Jint.Runtime/VM/AbstractBox.cs" Line="15" Column="41" />
+      <File FileName="Jint.Runtime/VM/Box.cs" Line="54" Column="41" />
+      <File FileName="Jint.Runtime/VM/OpCodes/BinaryOp.cs" Line="31" Column="51" />
+      <File FileName="Jint.Runtime/VM/Frame.cs" Line="41" Column="42" />
     </Files>
     <Pads>
       <Pad Id="ProjectPad">
@@ -19,11 +15,8 @@
           <Node name="Jint.Runtime" expanded="True">
             <Node name="VM" expanded="True">
               <Node name="OpCodes" expanded="True" />
+              <Node name="Frame.cs" selected="True" />
             </Node>
-            <Node name="VM2" expanded="True">
-              <Node name="OpCodes" expanded="True" />
-            </Node>
-            <Node name="Main.cs" selected="True" />
           </Node>
         </State>
       </Pad>