Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/MoonSharp.Interpreter/DataTypes/Annotation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace MoonSharp.Interpreter
{
public class Annotation
{
public string Name { get; private set; }
public DynValue Value { get; private set; }

public Annotation(string name, DynValue value)
{
Name = name;
Value = value;
}

public override string ToString()
{
return $"{Name}: {Value}";
}
}
}
12 changes: 10 additions & 2 deletions src/MoonSharp.Interpreter/DataTypes/Closure.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MoonSharp.Interpreter.Execution;

Expand Down Expand Up @@ -27,6 +28,11 @@ public enum UpvaluesType
/// </summary>
Closure
}

/// <summary>
/// Gets the annotations made on this function.
/// </summary>
public IReadOnlyList<Annotation> Annotations { get; private set; }


/// <summary>
Expand Down Expand Up @@ -59,12 +65,14 @@ public enum UpvaluesType
/// <param name="idx">The index.</param>
/// <param name="symbols">The symbols.</param>
/// <param name="resolvedLocals">The resolved locals.</param>
internal Closure(Script script, int idx, SymbolRef[] symbols, IEnumerable<Upvalue> resolvedLocals)
internal Closure(Script script, int idx, SymbolRef[] symbols, Annotation[] annotations, IEnumerable<Upvalue> resolvedLocals)
{
OwnerScript = script;

EntryPointByteCodeLocation = idx;

Annotations = annotations ?? Array.Empty<Annotation>();

if (symbols.Length > 0)
ClosureContext = new ClosureContext(symbols, resolvedLocals);
else
Expand Down
5 changes: 4 additions & 1 deletion src/MoonSharp.Interpreter/Execution/InstructionFieldUsage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ internal enum InstructionFieldUsage
Number = 0x8,
NumVal = 0x10,
NumVal2 = 0x20,
NumValAsCodeAddress = 0x8010
NumValAsCodeAddress = 0x8010,
Annotations = 0x10000
}

internal static class InstructionFieldUsage_Extensions
Expand Down Expand Up @@ -47,6 +48,8 @@ internal static InstructionFieldUsage GetFieldUsage(this OpCode op)
case OpCode.PushTrue:
case OpCode.PushFalse:
return InstructionFieldUsage.None;
case OpCode.Annot:
return InstructionFieldUsage.Annotations;
case OpCode.Pop:
case OpCode.Copy:
case OpCode.TblInitI:
Expand Down
8 changes: 7 additions & 1 deletion src/MoonSharp.Interpreter/Execution/ScriptLoadingContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MoonSharp.Interpreter.Debugging;
using System.Collections.Generic;
using MoonSharp.Interpreter.Debugging;
using MoonSharp.Interpreter.Tree;

namespace MoonSharp.Interpreter.Execution
Expand All @@ -14,6 +15,11 @@ class ScriptLoadingContext

public ScriptSyntax Syntax { get; set; }

//Compiler state
internal List<Annotation> ChunkAnnotations { get; set; } = new List<Annotation>();
internal List<Annotation> FunctionAnnotations { get; set; } = new List<Annotation>();


public ScriptLoadingContext(Script s)
{
Script = s;
Expand Down
9 changes: 9 additions & 0 deletions src/MoonSharp.Interpreter/Execution/VM/ByteCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@ public int Emit_Meta(string funcName, OpCodeMetadataType metaType)
NumVal2 = (int)metaType
});
}

public int Emit_Annot(Annotation[] annotations)
{
return AppendInstruction(new Instruction()
{
OpCode = OpCode.Annot,
Annotations = annotations
});
}


public int Emit_BeginFn(RuntimeScopeFrame stackFrame)
Expand Down
111 changes: 109 additions & 2 deletions src/MoonSharp.Interpreter/Execution/VM/Instruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ internal string String
get => _object as string;
set => _object = value;
}


internal Annotation[] Annotations
{
get => _object as Annotation[];
set => _object = value;
}


public override string ToString()
Expand Down Expand Up @@ -65,6 +70,9 @@ public override string ToString()
if (((usage & ((int)InstructionFieldUsage.SymbolList)) != 0) && (SymbolList != null))
append += " " + string.Join(",", SymbolList.Select(s => s.ToString()).ToArray());

if (((usage & ((int) InstructionFieldUsage.Annotations)) != 0) && (Annotations != null))
append += " " + string.Join(",", Annotations.Select((x => x.ToString())));

return append;
}

Expand All @@ -88,7 +96,8 @@ internal void WriteBinary(BinDumpWriter wr, int baseAddress, Dictionary<SymbolRe

if ((usage & ((int)InstructionFieldUsage.String)) == 0 &&
(usage & ((int)InstructionFieldUsage.Symbol)) == 0 &&
(usage & ((int)InstructionFieldUsage.SymbolList)) == 0 &&
(usage & ((int)InstructionFieldUsage.SymbolList)) == 0 &&
(usage & ((int)InstructionFieldUsage.Annotations)) == 0 &&
_object != null)
{
throw new Exception("Object usage");
Expand Down Expand Up @@ -121,6 +130,16 @@ internal void WriteBinary(BinDumpWriter wr, int baseAddress, Dictionary<SymbolRe
for (int i = 0; i < this.SymbolList.Length; i++)
WriteSymbol(wr, SymbolList[i], symbolMap);
}

if ((usage & ((int) InstructionFieldUsage.Annotations)) != 0)
{
wr.WriteVarUInt32((uint)this.Annotations.Length);
for (int i = 0; i < Annotations.Length; i++)
{
wr.WriteString(Annotations[i].Name);
WriteDynValue(wr, Annotations[i].Value, true);
}
}
}

private static void WriteSymbol(BinDumpWriter wr, SymbolRef symbolRef, Dictionary<SymbolRef, int> symbolMap)
Expand All @@ -137,6 +156,83 @@ private static SymbolRef ReadSymbol(BinDumpReader rd, SymbolRef[] deserializedSy
return deserializedSymbols[id - 1];
}

static void WriteDynValue(BinDumpWriter wr, DynValue d, bool allowTable)
{
switch (d.Type) {
case DataType.Nil:
wr.WriteByte((byte)d.Type);
break;
case DataType.Void:
wr.WriteByte((byte)d.Type);
break;
case DataType.Boolean:
if(d.Boolean) wr.WriteByte((byte)DataType.Boolean | 0x80);
else wr.WriteByte((byte)DataType.Boolean);
break;
case DataType.String:
wr.WriteByte((byte)d.Type);
wr.WriteString(d.String);
break;
case DataType.Number:
wr.WriteByte((byte)d.Type);
wr.WriteDouble(d.Number);
break;
case DataType.Table when allowTable:
wr.WriteByte((byte)d.Type);
WriteTable(wr, d.Table);
break;
case DataType.Table when !allowTable:
throw new Exception("Stored table key cannot be table");
default:
throw new Exception("Can only store DynValue of string/number/bool/nil/table");
}
}

static void WriteTable(BinDumpWriter wr, Table t)
{
//this enumerates twice. not ideal
wr.WriteVarInt32(t.Pairs.Count());
foreach (var p in t.Pairs)
{
WriteDynValue(wr, p.Key, false);
WriteDynValue(wr, p.Value, true);
}
}

static DynValue ReadDynValue(BinDumpReader rd, bool allowTable)
{
var b = rd.ReadByte();
var type = (DataType) (b & 0x7f);
switch (type) {
case DataType.Nil:
return DynValue.Nil;
case DataType.Void:
return DynValue.Void;
case DataType.Boolean:
if ((b & 0x80) == 0x80) return DynValue.True;
return DynValue.False;
case DataType.String:
return DynValue.NewString(rd.ReadString());
case DataType.Number:
return DynValue.NewNumber(rd.ReadDouble());
case DataType.Table when allowTable:
return ReadTable(rd);
default:
throw new InternalErrorException("Invalid DynValue storage in bytecode");
}
}

static DynValue ReadTable(BinDumpReader rd)
{
var d = DynValue.NewPrimeTable();
var table = d.Table;
var c = rd.ReadVarInt32();
for (int i = 0; i < c; i++) {
table.Set(ReadDynValue(rd, false), ReadDynValue(rd, true));
}
return d;
}

internal static Instruction ReadBinary(BinDumpReader rd, int baseAddress, Table envTable, SymbolRef[] deserializedSymbols)
{
Instruction that = new Instruction();
Expand Down Expand Up @@ -176,6 +272,17 @@ internal static Instruction ReadBinary(BinDumpReader rd, int baseAddress, Table
that.SymbolList[i] = ReadSymbol(rd, deserializedSymbols);
}

if ((usage & ((int) InstructionFieldUsage.Annotations)) != 0)
{
int len = (int) rd.ReadVarUInt32();
that.Annotations = new Annotation[len];
for (int i = 0; i < that.Annotations.Length; i++)
{
that.Annotations[i] = new Annotation(rd.ReadString(), ReadDynValue(rd, true));
}
}


return that;
}

Expand Down
1 change: 1 addition & 0 deletions src/MoonSharp.Interpreter/Execution/VM/OpCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ internal enum OpCode
CloseUp, // Close a specific upvalue

Meta, // Injects function metadata used for reflection things (dumping, debugging)
Annot, //Injects annotations
BeginFn, // Adjusts for start of function, taking in parameters and allocating locals
Args, // Takes the arguments passed to a function and sets the appropriate symbols in the local scope
Call, // Calls the function specified on the specified element from the top of the v-stack. If the function is a MoonSharp function, it pushes its numeric value on the v-stack, then pushes the current PC onto the x-stack, enters the function closure and jumps to the function first instruction. If the function is a CLR function, it pops the function value from the v-stack, then invokes the function synchronously and finally pushes the result on the v-stack.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ sealed partial class Processor
return meta;
}

internal Annotation[] FindAnnotations(int baseAddress)
{
Instruction meta = m_RootChunk.Code[baseAddress];

// skip nops
while (meta.OpCode == OpCode.Nop)
{
baseAddress++;
meta = m_RootChunk.Code[baseAddress];
}

if (meta.OpCode != OpCode.Meta)
return null;
baseAddress++;
if (m_RootChunk.Code[baseAddress].OpCode != OpCode.Annot)
return null;
return m_RootChunk.Code[baseAddress].Annotations;
}


internal void AttachDebugger(IDebugger debugger)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ private DynValue Processing_Loop(int instructionPtr, bool canAwait = false)
case OpCode.Nop:
case OpCode.Debug:
case OpCode.Meta:
case OpCode.Annot:
break;
case OpCode.Pop:
m_ValueStack.RemoveLast(i.NumVal);
Expand Down Expand Up @@ -494,9 +495,8 @@ private DynValue GetStoreValue(Instruction i)

private void ExecClosure(Instruction i)
{
Closure c = new Closure(this.m_Script, i.NumVal, i.SymbolList,
Closure c = new Closure(this.m_Script, i.NumVal, i.SymbolList, FindAnnotations(i.NumVal),
i.SymbolList.Select(s => this.GetUpvalueSymbol(s)).ToList());

m_ValueStack.Push(DynValue.NewClosure(c));
}

Expand Down
63 changes: 63 additions & 0 deletions src/MoonSharp.Interpreter/IAnnotationPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace MoonSharp.Interpreter
{
public enum AnnotationAction
{
Allow,
Ignore,
Error
}

public interface IAnnotationPolicy
{
AnnotationAction OnChunkAnnotation(string name, DynValue value);
AnnotationAction OnFunctionAnnotation(string name, DynValue value);
}

public static class AnnotationPolicies
{
public static IAnnotationPolicy Allow { get; } = new AllowPolicy();

public static IAnnotationPolicy Ignore { get; } = new IgnorePolicy();

public static IAnnotationPolicy Error { get; } = new ErrorPolicy();

class AllowPolicy : IAnnotationPolicy
{
public AnnotationAction OnChunkAnnotation(string name, DynValue value)
{
return AnnotationAction.Allow;
}

public AnnotationAction OnFunctionAnnotation(string name, DynValue value)
{
return AnnotationAction.Allow;
}
}

class IgnorePolicy : IAnnotationPolicy
{
public AnnotationAction OnChunkAnnotation(string name, DynValue value)
{
return AnnotationAction.Ignore;
}

public AnnotationAction OnFunctionAnnotation(string name, DynValue value)
{
return AnnotationAction.Ignore;
}
}

class ErrorPolicy : IAnnotationPolicy
{
public AnnotationAction OnChunkAnnotation(string name, DynValue value)
{
return AnnotationAction.Error;
}

public AnnotationAction OnFunctionAnnotation(string name, DynValue value)
{
return AnnotationAction.Error;
}
}
}
}
Loading