Advertisement
stdray

Basic Macro

Mar 20th, 2013
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.10 KB | None | 0 0
  1. #pragma indent
  2. using Nemerle;
  3. using Nemerle.Collections;
  4. using Nemerle.Compiler;
  5. using Nemerle.Compiler.Parsetree;
  6. using Nemerle.Compiler.Typedtree;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10.  
  11. namespace YobaBasic.Macro
  12.     public macro Basic(expr) syntax("BASIC", expr)
  13.         BasicIml.Transform(Macros.ImplicitCTX(), expr)
  14.  
  15.     public module BasicIml
  16.         public Transform(typer: Typer, expr : PExpr) : PExpr
  17.             Macros.DefineCTX(typer)
  18.             def getStrAndLoc(expr)
  19.                 | PExpr.Literal(Literal where(RawString = rs)) =>
  20.                     if (rs.Length == 0 || rs[0] != '<')
  21.                         Message.FatalError(expr.Location,
  22.                             "The literal in 'BASIC' macro must be recursive string.")
  23.                     else
  24.                         def str = rs.Substring(2, rs.Length - 4)
  25.                         def loc = expr.Location
  26.                         def loc = Location(loc.FileIndex, loc.Line, loc.Column + 2,
  27.                                            loc.EndLine, loc.EndColumn - 2)
  28.                         (str, loc)
  29.                 | _                                            =>
  30.                      Message.FatalError(expr.Location,
  31.                         "You must pass recursive string with basic code into 'BASIC' macro.")
  32.             def mkLines(vars, lines, gotoLines)
  33.                 def mkExpr(exprs)
  34.                     def filtered = exprs.Filter(e => !(e is <[ () ]> || e is <[]>))
  35.                     <[{..$filtered}]>
  36.                 def mkLabel(n, loc)
  37.                     if(gotoLines.Contains <| n)
  38.                         def voidv = typer.Manager.InternalType.Void
  39.                         PExpr.Typed(loc, TExpr.Label(voidv, n, voidv |> TExpr.DefaultValue))
  40.                     else <[]>
  41.                 def pvars = vars.Select(Name).Map(v => <[mutable $(v : name)]>)
  42.                 def pbody = lines \
  43.                     .OrderBy(_.num).NToList() \
  44.                     .FoldRight(<[]>, (l, a) => mkExpr <| [mkLabel(l.num, l.numloc), l.expr, a])
  45.                 mkExpr <| pvars + [pbody]
  46.             def mkError(parser)
  47.                 def (pos, expected) = parser.GetMaxRollbackPosAndNames()
  48.                 def expected = expected.NToList()
  49.                 def msg =
  50.                     if (expected.IsEmpty) "Unexpected character."
  51.                     else match (expected.DivideLast())
  52.                         | ([], last) => $"Expected $last."
  53.                         | (expected, last) => $"Expected ..$expected or $last."
  54.                 Message.FatalError(parser.ToLocation(pos, pos + 1), msg)
  55.             def (code, loc) = getStrAndLoc <| expr
  56.             typer.Env.Manager.MacroColors.PushUseSiteColor()
  57.             try
  58.                 def parser = BasicParser(loc, code, typer)
  59.                 match(parser.Parse <| code)
  60.                     | Some(r) => mkLines(parser.Variables, r, parser.GotoLines)
  61.                     | None    => mkError <| parser
  62.             catch
  63.                 | _ => <[]>
  64.             finally
  65.                 typer.Env.Manager.MacroColors.PopColor()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement