Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: DanielKeep/Dk.Dasm
base: e6f28aa858
...
head fork: DanielKeep/Dk.Dasm
compare: 5a95cd7ee9
  • 5 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
Commits on Apr 20, 2012
@DanielKeep Added Readme.md to solution.
Whoopsie.
e8548b5
@DanielKeep Added difference literals and data length literals.
~target, base~target plus ~ within a dat.
f2d03a1
Commits on Apr 21, 2012
@DanielKeep Refactored Assembler access to environment.
Assembler now does message output and file opening via a callback.  This will hopefully make it easier to get running with JSIL.
f239ede
@DanielKeep Added jsil to .gitignore. 0be3216
@DanielKeep Removed superfluous references. 5a95cd7
View
3  .gitignore
@@ -25,4 +25,5 @@ obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
-/packages/
+/packages/
+/jsil/
View
4 Dk.Dasm.Cli/Dk.Dasm.Cli.csproj
@@ -42,11 +42,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
View
5 Dk.Dasm.sln
@@ -5,6 +5,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dk.Dasm", "Dk.Dasm\Dk.Dasm.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dk.Dasm.Cli", "Dk.Dasm.Cli\Dk.Dasm.Cli.csproj", "{F160772C-F0B7-4A4B-A0DC-5C632BF0BD24}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC63B1A9-263C-4F87-B175-5789E044D1C3}"
+ ProjectSection(SolutionItems) = preProject
+ Readme.md = Readme.md
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
View
77 Dk.Dasm/Assembler.cs
@@ -15,6 +15,12 @@ namespace Dk.Dasm
/// </summary>
public class Assembler
{
+ public Assembler()
+ {
+ OnMessage = DefaultMessageHandler;
+ OnOpenFile = DefaultOpenFileHandler;
+ }
+
/// <summary>
/// Performs assembly based on the given options object.
/// </summary>
@@ -39,12 +45,11 @@ public void Assemble(AssemblerOptions options)
var p = new Parser(ld);
var pt = p.Parse(src, sourceFilePath);
- // TODO: Move these out somewhere.
+ // Emit error messages.
if (pt.ParserMessages.Count > 0)
{
foreach (var msg in pt.ParserMessages)
- Console.Error.WriteLine("{0}{1}: {2}",
- sourceFilePath, msg.Location, msg.Message);
+ Error(sourceFilePath, msg.Location, msg.Message);
throw new CodegenException("Compilation failed.");
}
@@ -65,7 +70,7 @@ public void Assemble(AssemblerOptions options)
* Write the output file.
*/
- using (var target = new FileStream(options.TargetPath, FileMode.Create))
+ using (var target = OpenFile(options.TargetPath, FileMode.Create))
{
switch (options.TargetFormat)
{
@@ -143,7 +148,7 @@ public void Assemble(AssemblerOptions options)
if (options.DumpSymbols)
{
- using (var f = new FileStream(
+ using (var f = OpenFile(
Path.ChangeExtension(options.TargetPath, "sym"),
FileMode.Create))
{
@@ -161,9 +166,69 @@ public void Assemble(AssemblerOptions options)
}
}
+ public enum MessageType
+ {
+ Error,
+ }
+
+ public struct Message
+ {
+ public string Path;
+ public int Line, Column;
+ public MessageType Type;
+ public string Text;
+ }
+
+ #region Callbacks
+ public delegate void MessageDelegate(ref Message message);
+ public MessageDelegate OnMessage;
+
+ public delegate Stream OpenFileDelegate(string path, FileMode mode);
+ public OpenFileDelegate OnOpenFile;
+ #endregion
+
+ #region Callback implementation & interface
+ private void DefaultMessageHandler(ref Message msg)
+ {
+ Console.WriteLine("{0}({1}:{2}): {3}: {4}",
+ msg.Path, msg.Line + 1, msg.Column + 1, msg.Type, msg.Text);
+ }
+
+ private Stream DefaultOpenFileHandler(string path, FileMode mode)
+ {
+ return new FileStream(path, mode);
+ }
+
+ private void Error(string path, SourceLocation location, string text)
+ {
+ if (OnMessage == null)
+ return;
+
+ var msg = new Message()
+ {
+ Path = path,
+ Line = location.Line,
+ Column = location.Column,
+ Type = MessageType.Error,
+ Text = text,
+ };
+ }
+
+ private Stream OpenFile(string path, FileMode mode)
+ {
+ return OnOpenFile(path, mode);
+ }
+ #endregion
+
private string ReadFile(string path)
{
- return File.ReadAllText(path);
+ using (var f = OpenFile(path, FileMode.Open))
+ {
+ using (var tr = new StreamReader(f))
+ {
+ return tr.ReadToEnd();
+ }
+ }
}
}
View
207 Dk.Dasm/Codegen/DasmCodegen.cs
@@ -34,6 +34,7 @@ public enum CodeType : byte
Instruction,
Literal,
Label,
+ Difference,
}
/// <summary>
@@ -57,6 +58,13 @@ public struct Code
public CodeFlags Flags;
public ushort Value;
+ public Code(CodeType type, ushort value)
+ {
+ this.Type = type;
+ this.Value = value;
+ this.Flags = CodeFlags.IsLiteral;
+ }
+
public Code(Instruction instr)
{
this.Type = CodeType.Instruction;
@@ -104,6 +112,25 @@ public Dcpu.Instruction Instruction
}
/// <summary>
+ /// Represents a difference literal.
+ /// </summary>
+ public struct Difference
+ {
+ public Code Base, Target;
+
+ public Difference(Code @base, Code target)
+ {
+ this.Base = @base;
+ this.Target = target;
+ }
+
+ public Difference(ushort @base, Code target)
+ : this(new Code(@base), target)
+ {
+ }
+ }
+
+ /// <summary>
/// This is the global label prepended to local labels
/// *before* the first user-defined global label.
/// </summary>
@@ -126,6 +153,16 @@ public struct CgContext
/// Emit a code word to the output.
/// </summary>
public CodeWriter Write;
+ /// <summary>
+ /// The current length of the code array.
+ /// </summary>
+ public Func<ushort> GetCurrentAddress;
+ /// <summary>
+ /// Callback to emit a difference to the code array. We need
+ /// a separate callback since a difference won't actually
+ /// fit in a Code.
+ /// </summary>
+ public Func<Difference, Code> EncodeDifference;
}
/// <summary>
@@ -185,6 +222,12 @@ public CgResult CgProgram(ParseTreeNode node)
*/
var code = new List<Code>();
/*
+ * This array stores difference literals. We need to do this
+ * since difference literals can depend on labels but won't
+ * fit in a code.
+ */
+ var diffLits = new List<Difference>();
+ /*
* We also need something to keep track of the defined labels.
* Since we need to be able to pack this into code entries,
* we'll stick them in a flat array.
@@ -229,10 +272,22 @@ public CgResult CgProgram(ParseTreeNode node)
{
code.Add(c);
};
+ Func<Difference, Code> diffToCode = delegate(Difference diff)
+ {
+ var index = (ushort)diffLits.Count;
+ diffLits.Add(diff);
+ return new Code(CodeType.Difference, index);
+ };
/*
* Whack 'em in a context.
*/
- var ctx = new CgContext { Lookup = lookup, Write = write };
+ var ctx = new CgContext
+ {
+ Lookup = lookup,
+ Write = write,
+ GetCurrentAddress = () => (ushort)code.Count,
+ EncodeDifference = diffToCode,
+ };
/*
* Ok, let's process those lines.
*/
@@ -266,6 +321,9 @@ public CgResult CgProgram(ParseTreeNode node)
label.Fix(labels[fix.Value], labelNode.Span);
break;
+ case CodeType.Difference:
+ throw new CodegenException("Labels cannot be fixed to difference literals");
+
default:
throw new UnexpectedGrammarException();
}
@@ -333,22 +391,31 @@ public CgResult CgProgram(ParseTreeNode node)
/*
* Now we can produce the output image.
*/
+ Func<Code, ushort> evalCode = null;
+ evalCode = delegate(Code c)
+ {
+ switch (c.Type)
+ {
+ case CodeType.Label:
+ return labels[c.Value].Value;
+
+ case CodeType.Difference:
+ {
+ var diff = diffLits[c.Value];
+ return (ushort)(evalCode(diff.Target) - evalCode(diff.Base));
+ }
+
+ default:
+ return c.Value;
+ }
+ };
+
var image = new ushort[code.Count];
{
var i = 0;
foreach (var c in code)
{
- switch (c.Type)
- {
- case CodeType.Label:
- image[i] = labels[c.Value].Value;
- break;
-
- default:
- image[i] = c.Value;
- break;
- }
-
+ image[i] = evalCode(c);
++i;
}
}
@@ -431,51 +498,58 @@ public void CgData(ParseTreeNode node, ref CgContext ctx)
{
var args = node.ChildNodes[1];
+ var i = 0;
foreach (var arg in args.ChildNodes)
- CgDataValue(arg, ref ctx);
+ {
+ if (arg.Term.Name == "DataLength")
+ ctx.Write(new Code(CountDataWords(args, i + 1, ref ctx)));
+
+ else
+ CgDataValue(arg, ref ctx);
+
+ ++i;
+ }
}
- public void CgDataValue(ParseTreeNode node, ref CgContext ctx)
+ public ushort CountDataWords(ParseTreeNode datNode, int startAt, ref CgContext ctx)
{
- // DataValue is transient
- // DataValue = string | number | character | identifier
- switch (node.Term.Name)
+ var acc = (ushort)0;
+
+ for (var i = startAt; i < datNode.ChildNodes.Count; ++i)
{
- case "character":
- {
- var ch = EvalCharacter(node, ref ctx);
- ctx.Write(new Code(ch));
- }
- break;
+ var val = datNode.ChildNodes[i];
- case "identifier":
- {
- var l = EvalIdentifier(node, ref ctx);
- var c = new Code(l);
- c.Flags |= CodeFlags.IsLiteral;
- ctx.Write(c);
- }
- break;
+ switch (val.Term.Name)
+ {
+ case "string":
+ acc += (ushort)EvalString(val, ref ctx).Length;
+ break;
- case "number":
- {
- var v = EvalNumber(node, ref ctx);
- ctx.Write(new Code(v));
- }
- break;
+ default:
+ acc++;
+ break;
+ }
+ }
- case "string":
- {
- var s = EvalString(node, ref ctx);
- foreach (var ch in s)
- {
- ctx.Write(new Code(ch));
- }
- }
- break;
+ return acc;
+ }
- default:
- throw new UnexpectedGrammarException();
+ public void CgDataValue(ParseTreeNode node, ref CgContext ctx)
+ {
+ // DataValue is transient
+ // DataValue = [tilde |] string | number | character | identifier
+
+ // Note that ~ is handled by the caller since, by this point, it's
+ // too late to do anything.
+ if (node.Term.Name == "string")
+ {
+ var s = EvalString(node, ref ctx);
+ foreach (var ch in s)
+ ctx.Write(new Code(ch));
+ }
+ else
+ {
+ ctx.Write(EvalLiteralWord(node, ref ctx));
}
}
@@ -605,18 +679,43 @@ public ushort CgLiteralLookup(ParseTreeNode node, ref CgContext ctx, out Code? t
public Code EvalLiteralWord(ParseTreeNode node, ref CgContext ctx)
{
- var child = node.ChildNodes[0];
+ var head = node.ChildNodes[0];
+ var tail = node.ChildNodes.Count > 1 ? node.ChildNodes[1] : null;
+
+ var code = EvalLiteralWordAtom(head, ref ctx);
- switch (child.Term.Name)
+ if (tail != null)
{
- case "character":
- return new Code(EvalCharacter(child, ref ctx));
+ var tailC = EvalLiteralWordAtom(tail, ref ctx);
+ var diff = new Difference(code, tailC);
+ code = ctx.EncodeDifference(diff);
+ }
+ return code;
+ }
+
+ public Code EvalLiteralWordAtom(ParseTreeNode node, ref CgContext ctx)
+ {
+ switch (node.Term.Name)
+ {
case "identifier":
- return new Code(EvalIdentifier(child, ref ctx));
+ return new Code(EvalIdentifier(node, ref ctx));
+
+ case "character":
+ return new Code(EvalCharacter(node, ref ctx));
case "number":
- return new Code(EvalNumber(child, ref ctx));
+ return new Code(EvalNumber(node, ref ctx));
+
+ case "DifferenceLiteral":
+ {
+ var @base = ctx.GetCurrentAddress();
+ var target = EvalLiteralWordAtom(node.ChildNodes[0].ChildNodes[0], ref ctx);
+ return ctx.EncodeDifference(new Difference(@base, target));
+ }
+
+ case "DifferenceTo":
+ return EvalLiteralWordAtom(node.ChildNodes[0], ref ctx);
default:
throw new UnexpectedGrammarException();
View
56 Dk.Dasm/DasmGrammar.cs
@@ -37,8 +37,9 @@ public DasmGrammar(Options options)
var minus = ToTerm("-");
var lbracket = ToTerm("[");
var rbracket = ToTerm("]");
+ var tilde = ToTerm("~");
- MarkPunctuation(comma, colon, atsym, lbracket, rbracket);
+ MarkPunctuation(comma, colon, atsym, lbracket, rbracket, tilde);
#endregion
#region Non-Terminals
@@ -102,7 +103,15 @@ public DasmGrammar(Options options)
DataArguments.Rule = MakePlusRule(DataArguments, comma, DataValue);
MarkTransient(DataValue);
- DataValue.Rule = stringLit | numberLit | charLit | ident;
+ DataValue.Rule = stringLit | LiteralWord;
+
+ if (options.DatLengthCounting)
+ {
+ var DataLength = new NonTerminal("DataLength");
+ DataValue.Rule = DataValue.Rule | DataLength;
+
+ DataLength.Rule = tilde;
+ }
MarkTransient(Reg);
Reg.Rule = GeneralReg | SpecialReg;
@@ -120,11 +129,37 @@ public DasmGrammar(Options options)
StackOp.Rule = ToTerm("push") | "pop" | "peek";
- LiteralWord.Rule = charLit | numberLit | ident;
+ var LiteralWordAtom = new NonTerminal("LiteralWordAtom");
+
+ LiteralWord.Rule = LiteralWordAtom;
+
+ MarkTransient(LiteralWordAtom);
+ LiteralWordAtom.Rule = charLit | numberLit | ident;
LiteralLookup.Rule = "[" + LiteralWord + "]";
#endregion
+ #region Optional Non-Terminals
+ if (options.DifferenceLiteral)
+ {
+ var DifferenceLiteral = new NonTerminal("DifferenceLiteral");
+ var DifferenceLiteralOpt = new NonTerminal("DifferenceLiteral?");
+
+ // We do this rather than use LiteralWordAtom directly so
+ // that if something changes later on, we (hopefully) don't
+ // need to update this code.
+ var litword = LiteralWord.Rule;
+
+ // ~ lit | lit [ ~ lit ]
+ LiteralWord.Rule = DifferenceLiteral | litword + DifferenceLiteralOpt;
+
+ DifferenceLiteral.Rule = tilde + Named("DifferenceTo", litword);
+
+ MarkTransient(DifferenceLiteralOpt);
+ DifferenceLiteralOpt.Rule = tilde + Named("DifferenceTo", litword) | Empty;
+ }
+ #endregion
+
#region Language Flags
this.LanguageFlags = Irony.Parsing.LanguageFlags.NewLineBeforeEOF;
#endregion
@@ -240,6 +275,19 @@ public class Options
/// this boils down to '$'.
/// </summary>
public bool ExtendedLabelNames = false;
+ /// <summary>
+ /// This allows you to use ~ in a dat statement which resolves
+ /// to the number of words remaining in the statement.
+ /// </summary>
+ public bool DatLengthCounting = false;
+ /// <summary>
+ /// Distance literals (~addr) are replaced with the
+ /// distance from their location to the specified address.
+ ///
+ /// You can also use addr1~addr2 to compute the distance
+ /// between two arbitrary locations in code.
+ /// </summary>
+ public bool DifferenceLiteral = false;
/// <summary>
/// Options that conform to standard assembler syntax.
@@ -263,6 +311,8 @@ static Options()
BinaryLiterals = true,
LocalLabels = true,
ExtendedLabelNames = true,
+ DatLengthCounting = true,
+ DifferenceLiteral = true,
};
}
}
View
4 Dk.Dasm/Dk.Dasm.csproj
@@ -36,11 +36,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Assembler.cs" />

No commit comments for this range

Something went wrong with that request. Please try again.