GithubHelp home page GithubHelp logo

rsdn / nitra Goto Github PK

View Code? Open in Web Editor NEW
144.0 43.0 11.0 187.69 MB

Nitra is a language workbench

License: Apache License 2.0

Batchfile 0.15% Nemerle 69.12% C# 29.00% HTML 0.09% XSLT 0.18% CSS 0.04% Smalltalk 0.01% Roff 1.43%
nitra-is-a-language-workbench

nitra's Introduction

Nitra

Nitra

Nitra is a language workbench. You can use Nitra for the creation or extension of a general-purpose programming language or a domain-specific language (DSL). At present Nitra allows you to create dynamically expanding parsers. In the future, Nitra will allow to create full support for programming languages: compilers, IDE support.

License — BSD 3-Clause License

Join the chat at https://gitter.im/rsdn/nitra - chat for interactive discussions

Russian forum

Build — building Nitra project from sources.

Example — string calculator example

Roadmap

Languages powered by Nitra

Autogenerated Visual Studio plug-in for Nitra powered language (extencible C#): VS Plagin

nitra's People

Contributors

dependabot[bot] avatar ionoy avatar pekabon avatar rampelstinskin avatar someone-with-default-username avatar ssrmm avatar stitchous avatar vasily-kirichenko avatar vladd2 avatar vladimirreshetnikov avatar xxvisorxx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nitra's Issues

[VS Plugin] Exception when unloading project

Unloading a project in VisualStudio (Solution Explorer -> right-click -> Unload Project) produces

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

reloading it produces in some cases

System.ArgumentException: An item with the same key has already been added.

Both error messages happen on the server side.

Note that this does not prevent the plugin from working, but it's something that should be fixed nontheless.

cant build nitra

hi, ive added the immutable dll to gac and build doesnt work, msbuild cant find the dll

NullReferenceException when accessing Dependent Property of decomposed list element

In the below example Foo is a mandatory element of the Attribute list. However in the test program it is not present. In the current implementation this causes Foo to be null. Consequently setting or retrieving a property on it results in a NullReferenceException. Instead of null, Foo should be AmbiguousOrMissing.


Test Program:

Bar;

Grammar and AST:

namespace Test
{
  /***  Syntax  ***/

  syntax module TestSyntax
  {    
    using Nitra.Core;

    [StartRule]
    syntax Test = (Attribute ';' nl)+;

    token Attribute
    {
      | Foo = "Foo";
      | Bar = "Bar";
    }
  }

  /***  AST  ***/

  ast TestAst
  {
    Foo.Test = "Foo"; // System.NullReferenceException

    decompose Attributes
    {
      Foo : Attribute.Foo;
      Bar : Attribute.Bar;
    }

    Attributes : Attribute*;
  }

  abstract ast Attribute
  {
    | Foo { in Test : string; }
    | Bar {}
  }

  /***  Mapping  ***/

  map syntax TestSyntax.Test -> TestAst
  {
    Attributes -> Attributes;
  }

  map syntax TestSyntax.Attribute -> Attribute
  {
    | Foo -> Foo {}
    | Bar -> Bar {}
  }
}

AST: Cannot use implicit cast

Using an implicit cast when assigning some property results in a compilation error:

namespace Test.Ast
{
  ast Foo 
  {
    in Test1 : string;

    Test1 = StringWrapper("Test"); // error : Unexpected expression 'this.Test1 = (macro_Nitra.PExprAnchorMacro:     
  }                                //	  DEBUG_INFO(Test.StringWrapper ("Test")) :> string)' Assign
}
namespace Test
{
  [Record]
  class StringWrapper
  {
      private Value : string;
      
      public static @:(sw : StringWrapper) : string
      {
          sw.Value
      }
  }
}

Too many unindents cause ArgumentOutOfRangeException when pretty-printing

The following code produces System.ArgumentOutOfRangeException during pretty-printing:

namespace Test
{
  syntax module TestSyntax
  {
    using Nitra.Core;

    [StartRule]
    syntax Foo = "foo" nl '{' inl "bar" nl d d '}'; 
  } //            Too many decrements here --^
}
System.ArgumentOutOfRangeException: Count cannot be less than zero
Parameter name: repeatCount
   at System.Text.StringBuilder.Append(Char value, Int32 repeatCount)
   at Nitra.StringPrettyPrintWriter.IndentCurrentLine() in D:\<...>\Nitra\Nitra\Nitra.Runtime\PrettyPrint\StringPrettyPrintWriter.n:Line 178.
   at Nitra.StringPrettyPrintWriter.Unindent() in D:\<...>\Nitra\Nitra\Nitra.Runtime\PrettyPrint\StringPrettyPrintWriter.n:Line 151.
   at Test.TestSyntaxParseTree.Foo.PrettyPrint(PrettyPrintWriter writer, Int32 callerBindingPower, SpanClass spanClass) in C:\Users\<...>\AppData\Local\Temp\_N_GeneratedSource_BugTests.n:Line 473.
   at Nitra.ParseTree.ToString(PrettyPrintOptions options) in D:\<...>\Nitra\Nitra\Nitra.Runtime\ParseTree\ParseTree.n:Line 45.
   at Nitra.ParseTree.ToString() in D:\<...>\Nitra\Nitra\Nitra.Runtime\ParseTree\ParseTree.n:Line 32.
   at System.String.Concat(Object arg0, Object arg1)
   at TestApp.Program.Main(String[] args) in d:\<...>\Program.cs:Line 31.

Ideally this would be a compile time error instead.

[VS Plugin] Some error messages are not displayed

Some of the produced error messages are not shown in Visual Studio. Consider the following example with the C# grammar

namespace CSharp
{
    public class Program
    {}
    
    public class Program
    {}
    
    public class Tester
    {
        public Program Test()
        {
            throw new System.NotImplementedException();
        }
    }
}

Inside Visual Studio this produces only one error message:

Symbol 'Program' is ambiguous.

In the visualizer however the same program and the same grammar produce a total of 8 errors:

Visualizer Errors

That means currently only error message 3 is shown in VisualStudio. However, error messages 1, 2, 4 and 5 should also be displayed. Messages 6, 7 and 8 seem to be a minor bug in the grammar or the visualizer and shouldn't be relevant for this.

spelling and grammar corrections for https://github.com/rsdn/nitra/wiki/HintML

Spelling and grammar corrections ( OLD -> NEW ) :
compaler -> compiler
HintML HintML is based on XML -> HintML is based on XML
or a embedded hint -> or an embedded hint
allows you to specify name of a span -> allows you to specify the name of a span
navigate through a code -> navigate through a piece of code
monospaced font for a code -> monospaced font to signify a code block
the HintML module to make a hint code -> the HintML module to make hint code

Self-defined void-rules produce whitespace when pretty-printing

Consider the following grammar:

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;

    [StartRule]
    token Expression = ws Type ws sm Identifier ws ';';

    regex Identifier = ['a'..'z']+;

    void ws = Whitespace*;

    token Type
    {
      | "int"
      | "float"
    }
  }
}

When pretty-printing a correct declaration in the described language the ws-rule is printed as a single space.
The built-in rules s and S don't produce any whitespace during pretty-print, which seems more logical and useful to me.

Using box selection confuses Visual Studio Plugin

By pressing the Alt-key Visual Studio allows to select multiple rows and write to all of them simultaneously. When doing this the plugin gets confused. It shows incorrect error messages and the highlighting is wrong as well.

As an example see the following demo:

Bug Demo

Macro Ssub System for Syntax Generation - Syntax Binders / Syntax Variables, Parameterisation / Generics / Templating, Syntax Maching and Syntax Builders

I think add this to Nitra will increase its expressive power

  • Syntax Binders / Syntax Variables (will not be part of syntax definition unless explicitly used in syntax definition)
    • Make all Nira statements like expressions (ability to save parts of the syntax in binders for later reference)
    • Ability to define binders to the expressions (save parts of the definitions for reuse)
    • And Or relationships with expressions (this syntax or / and that syntax)
  • Parameterisation
    • Given a set of parameters generate different syntaxes like a function
  • Syntax search and matching
  • Syntax Builder (Interface / Type Class like syntax creation - search for context dependent matching syntax and apply it to a template)

This will hopefully remove the verbosity of the current scheme and make it more concise.

Maybe you can borrow ideas from http://www.rascal-mpl.org/. http://flix.github.io/

Unresolved "using" does not produce an error

The following Code does not produce any errors and is even working at runtime:

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;
    using Inexistent.Namesace;

    [StartRule]
    syntax Expression
    {
      | Foo = "FOO"
      | Bar = "BAR"
    }
  }
}

Since using Inexistent.Namesace; references something that doesn't exist, I would expect a compiler error instead.

Runtime Exception when pretty printing grammar

I have this grammar:

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;

    [StartRule]
    syntax Expression = (Foo; nl)+;

    syntax Foo = "foo";
  }
}

When I'm pretty-printing any accepted string that consists of more than one "foo" I get an System.ArgumentOutOfRangeException. Input that produces the error is e.g. "foofoo", "foo foo" or "foofoo foo". The only input that can be pretty printed is "foo".

If I change the rule syntax Expression = (Foo; nl)+; to syntax Expression = Foo+; or syntax Expression = (Foo nl)+;, then it works correctly. Other pretty-print markers like sm and inl produce the same result.


Some more infos for debugging purposes

The stack trace (might not be that useful because of the generated sources):

Unhandled Exception: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: id
   at Test.TestParseTree.Expression.__Parsed__Node.__ReadSequenceParseTreeStandardMode(Int32 id, Int32& pos) in C:\Users\<...>\AppData\Local\Temp\_N_GeneratedSource_Experiments.n:Line 392.
   at Nitra.Internal.ParseTreeFactory.CreateListWithSeparatorOnlyItems[TItemLoader,TItem,TSeparatorLoader](ParseResult parseResult, ISequenceParseTreeLoader`1itemLoader, Int32 itemSequenceId, ParseTreeCastHelper`2 itemConverter, ISequenceParseTreeLoader`1 separatorLoader, Int32 separatorSequenceId, Int32 rawTreePtr,Int32 offset, Int32& pos) in D:\<...>\Nitra\Nitra\Nitra.Runtime\ParseTree\ParseTreeFactory.n:Line 187.
   at Test.TestParseTree.Expression.__Parsed__Node.get_Foos() in C:\Users\<...>\AppData\Local\Temp\_N_GeneratedSource_Experiments.n:Line 260.
   at Test.TestParseTree.Expression.PrettyPrint(PrettyPrintWriter writer, Int32 callerBindingPower, SpanClass spanClass) in C:\Users\<...>\AppData\Local\Temp\_N_GeneratedSource_Experiments.n:Line 380.
   at Nitra.ParseTree.ToString(PrettyPrintOptions options) in D:\<...>\Nitra\Nitra\Nitra.Runtime\ParseTree\ParseTree.n:Line 45.
   at Nitra.ParseTree.ToString() in D:\<...>\Nitra\Nitra\Nitra.Runtime\ParseTree\ParseTree.n:Line 32.
   at System.String.Concat(Object arg0, Object arg1)
   at TesstApp.Program.Main(String[] args) in d:\<...>\Program.cs:Line 23.

The test program I used:

using System;
using Nitra;
using Nitra.ProjectSystem;

namespace TesstApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Write("> ");
            var input = Console.ReadLine();

            while (input != string.Empty)
            {
                var session = new ParseSession(Test.Test.Expression, compilerMessages: new ConsoleCompilerMessages());

                var result = session.Parse(input);

                if (result.IsSuccess)
                {
                    Console.WriteLine("Parsing succeeded!");
                    Console.WriteLine("PrettyPrint: " + result.CreateParseTree());
                }
                else
                {
                    Console.Error.WriteLine("Parsing failed!");
                }

                Console.Write("> ");
                input = Console.ReadLine();
            }
        }
    }
}

Create VS addin project skeleton

  • Create an empty VS extension project in VS 2013, targeting VS 2013 and VS 2015
  • Place all referenced assemblies into a folder inside the repository
  • Make it build on a machine without any VS SDK installed
  • Create a couple of scripts
    • Builds the project (result: VSIX file)
    • Same as above + install (register) the VSIX into all installed VS versions

Mapping not possible with syntax rules defined in other assembly

Syntax (defined in first assembly):

namespace Syntax
{
  syntax module Test
  {
    using Nitra.Core;

    [StartRule]
    syntax Foo = "foo";
  }
}

AST and mapping (defined in second assembly):

using Nitra;
using Nitra.Declarations;

namespace Ast
{
  ast Foo {}
}
using Nitra;
using Nitra.Runtime;
using Nitra.Declarations;

namespace Mapping
{
  map syntax Syntax.Test.Foo -> Ast.Foo {}
}

When compiling, this produces the error message error : AST mapping is not allowed here

This seems to be caused here: ruleSymbol is of type Nitra.Typing.ExternalSimpleRuleSymbol (generated from ExportableSymbol macro at SimpleRuleSymbol), whereas it is of type Nitra.Typing.ParsedSimpleRuleSymbol when it is located in the same assembly.

Nitra.Typing.ExternalSimpleRuleSymbol does not implement it's own version of AddSyntaxMapping() and so the generic one of SyntaxRuleSymbol gets chosen and produces the error message.

Design and implement Backends API

I think "Design and implement Backends API" is not necessary or should be available as and additional option of using the same front end technology for the back end.

Having a separate back end API increases the learning curve and you have to learn both the front end and back end schematics. Also it creases the maintenance surface area as well as potential bugs.

Best is to have the same front end technology be used for both ends. Any .Net IL/CLR can be parsed as an language and parsed into the Nitra AST format. Also the AST should be convertible to the original format it passed. So the process of code generation should be: Language -> Language AST -> Language AST Optimisations -> transform -> Output AST -> Output AST Optimisations -> Output, where Output can be .Net IR/CIL/IL or any other format like native machine code, LLVM, Java ByteCode or even other languages like JavaScript. This way you do not need a separate backend and frontend.

Only minor additions is that you should be able to:

  • encode/decode binary
  • parse binary treating it like as if it was written in a text based language like assembly code

Visual Studio plugin doesn't work with System.Collctions.Immutable >1.1.37

When compiling a generated plugin the reference to System.Collections.Immutable is not resolved as expected: If the Languages subfolder contains a System.Collections.Immutable.dll(which it usually does), then that one takes precedence over the one from the NuGet package specified in the hint-path.

For both the Nitra and the NitraCSharp plugin this is currently version 1.1.37. Therefor the compiled plugin-dll references version 1.1.37 instead of 1.2.0 (as specified by the reference in the .nprojfile). This by itself isn't a problem yet, but it hides one:
Visual Studio 2015 currently ships System.Collections.Immutable 1.1.37 as a private assembly (see C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies) and an assembly redirect for all version prior to 1.1.37 (see %LOCALAPPDATA%\Microsoft\VisualStudio\14.0\devenv.exe.config). In order to reduce the file size of VSIXs MSBuild excludes VisualStudio assembles from it.

In order to make the reference to System.Collections.Immutable resolve correctly, I changed it to require the specific version:

<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  <HintPath>packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
  <Private>True</Private>
</Reference>

This however breaks the plugin: MSBuild still excludes the dll from the VSIX, however 1.2.0 can no longer be supplied by VS itself and an assembly binding failure is happening at runtime. This will also happen as soon as Nitra is updated to a newer version of System.Collections.Immutable.

I've found a blog that provides a way to force the assembly to be included in the VSIX, however I didn't thy it out yet. The alternative would be to stay with 1.1.37 (or whatever VS ships with a future update) everywhere. This doesn't seem very useful though, because VS 2015 will probably get two more updates and that's it.

TL;DR

  1. System.Collections.Immutable should be referenced with specific version to ensure that the assembly is resolved as expected.
  2. System.Collections.Immutable should be included in the VSIX or it should be ensured that Nitra doesn't use a version >1.1.37 anywhere.

Assertion Exception when parsing grammar

The following grammar produces an assertion error during parsing (i.e. showing a modal modal dialog that has to be clicked away):

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;

    [StartRule]
    syntax Expression = (Foo ';' nl)+;

    token Foo
    {
      regex Foo = "foo";
    }
  }
}

I'm not really sure if that's actually a supported syntax. But either way it should behave differently: If it is syntactically valid, it should work; if it isn't, there should be an error at compile-time, not an assertion error at runtime.

As a side-note:

token Foo = Foo
{
  regex Foo = "foo";
}

does work, so it seems reasonable to me that the shorthand syntax should be valid as well.


Stacktrace of the assertion:

at Nitra.Internal.Recovery.TokenChanges..ctor(Int32 inserted, Int32 deleted) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Internal\Recovery\TokenChanges.n:Line 25.
at Nitra.Internal.Recovery.RecoveryParser.InsertSubrules(Int32 maxPos) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Internal\Recovery\RecoveryParser\RecoveryParser.Insert.n:Line 47.
at Nitra.Internal.Recovery.RecoveryParser.RecoveryFromAllErrors() in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Internal\Recovery\RecoveryParser\RecoveryParser.n:Line 126.
at Nitra.ParseSession._N__N_lambda__33699__33715.apply_void(IParseResult parseResult) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseSession.n:Line 82.
at Nitra.ParseResult.ParseImpl() in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseResult.n:Line 116.
at Nitra.ParseResult.Parse() in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseResult.n:Line 70.
at Nitra.ParseSession.Parse(SourceSnapshot sourceSnapshot) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseSession.n:Line 106.
at Nitra.ParseSession.Parse(String sourceText) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseSession.n:Line 88.
at TesstApp.Program.Main(String[] args) in d:\<...>\Program.cs:Line 24.

Stacktrace of the Nitra.ParsingFailureException that is produced afterwards, probably as a result of the failed assertion

Unexpected token: 'a'
   at Nitra.ParseResult.ParseImpl() in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseResult.n:Line 130.
   at Nitra.ParseResult.Parse() in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseResult.n:Line 70.
   at Nitra.ParseSession.Parse(SourceSnapshot sourceSnapshot) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseSession.n:Line 105.
   at Nitra.ParseSession.Parse(String sourceText) in C:\NitraBase\Nitra\Nitra\Nitra.Runtime\Parsing\ParseSession.n:Line 88.
   at TesstApp.Program.Main(String[] args) in d:\<..>\Program.cs:Line 24.

I've used the following test program along with a configuration entry that "redirects" the error message of the popups to a logfile (see https://msdn.microsoft.com/en-us/library/ty5e4c4h.aspx)

using System;
using Nitra;
using Nitra.ProjectSystem;

namespace TesstApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Write("> ");
            var input = Console.ReadLine();

            while (input != string.Empty)
            {
                try
                {
                    var session = new ParseSession(Test.Test.Expression, compilerMessages: new ConsoleCompilerMessages());

                    var result = session.Parse(input);

                    if (result.IsSuccess)
                    {
                        Console.WriteLine("Parsing succeeded!");
                    }
                    else
                    {
                        Console.Error.WriteLine("Parsing failed!");
                    }

                    Console.WriteLine("PrettyPrint: " + result.CreateParseTree());
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine("An exception of type {0} was not handled.", e.GetType());
                    Console.Error.WriteLine(e.Message);
                    Console.Error.WriteLine(e.StackTrace);
                }

                Console.Write("> ");
                input = Console.ReadLine();
            }
        }
    }
}

Do not working IgnoreToken

capture

`
syntax CompilationUnit = TypeDeclaration* !Any;
syntax TypeDeclaration = nl asnIdentifier s sm "::=" s sm TypeDefinition nl;
syntax TypeDefinition
{
syntax EnumDefinition = OpenBlock CloseBlock;
| Enumerated = ENUMERATED EnumDefinition;
}
token Comment
{
| [ExplicitSpaces]SingleLine = "--" (!NewLine Any)* NewLine?;
}

extend token IgnoreToken
{
| Comment;
}
`

Assertion exception when generating AST

The following code produces an assertion exception upon generation of the AST:

using Nitra;

namespace Test
{
  syntax module TestSyntax
  {    
    using Nitra.Core;

    [StartRule]
    syntax Test = FooBar=("Foo" sm "Bar"?) ';';
  }

  ast TestAst
  {
    Content : string;
  }

  map syntax TestSyntax.Test -> TestAst
  {
    Content = ParsedValue(FooBar.Span, GetText(FooBar.Span));
  }
}

The exception happens at the assert in ParseResult.n#L355

In order for this error to happen, Bar must be optional and FooBar must surround both Foo and Bar

Type Inference DSL

Type inference rules in languages maybe different. So provide a way to specify type inference rules. Also ability to scope it to particular areas in case of internal DSLs.

Inconsistent behaviour of using-statements

using-statements in syntax modules apply to the scope they are declared in:

namespace Foo
{
  syntax module Bar
  {
    using Nitra.Core;

    [StartRule]
    syntax Start = "foo" sm "bar"; // Nitra.Core visible here
  }
}

For namespaces however this is not not the case. The types opened by the using-statement are only visible in nested namepaces:

namespace Foo
{
  using Nitra;
  using Nitra.Declarations;

  declaration Root : Container {} // error : Unbound name 'Container'

  namespace Bar
  {
    declaration Root : Container {} // works fine in here
  }
}

This is somewhat inconsistent and should be changed so that elements opened through the using-statement are visible in the scope of that using-statement.

Erroneous syntax definition causes KeyNotFoundException

The following syntax definition produces a KeyNotFoundException during parsing:

namespace Test
{
  using Nitra.Core;

  syntax module TestSyntax
  {
    syntax Foo = Bar '+ Bar; // Note: The single quote is missing after the plus sign
    
    regex Bar = "Bar";
  }
}

The expected behaviour would be to get some parse errors instead.

Members of nested namespace not visible inside nested namespace

The following program causes the compiler error error : unbound type name `Bar'

namespace Test
{
  namespace InnerTest
  {
    ast Foo
    {
      BarProperty : Bar;
    }

    ast Bar {}

  }
}

One needs to either qualify the type with InnerTest.Bar or fully qualify it with Test.InnerTest.Bar to be able to compile the program.

Since Foo and Bar are defined in the same namespace they should be visible even if they are not qualified.

Unqualified property names are not allowed in interpolated strings

abstract ast BoolExpr : Binary
{
   Type = context.GetBoolSymbol();
}

abstract ast OrAndExpr : BoolExpr
{
  when (Expr1.Type != Type) Error($"Expected boolean expression but found $(self.Expr1.Type).");
  when (Expr2.Type != Type) Error($"Expected boolean expression but found $(self.Expr2.Type).");
}

If I try to use unqualified name for Expr1/Expr2 in the string interpolation, like this:

when (Expr1.Type != Type) Error($"Expected boolean expression but found $(Expr1.Type).");

then I get the following error: unbound name 'Expr1'

I think it's rather inconsistent that it's OK to use unqualified prop name in when condition, but it's not in string interpolation.

codefixes

in future wil it be available to enable codefixes on a custom language?

Endless loop during parsing

The following grammar produces an endless loop when parsing any invalid input:

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;

    [StartRule]
    [ExplicitSpaces]
    syntax Expression = Foo;

    regex Foo ='a';
  }
}

It seems to be related to the ExplicitSpaces: A token rule shows the same behavior, a syntax rule without the ExplicitSpaces attribute works as expected.

Quickly attaching the debugger showed that Nitra is stuck somewhere in the error-recovery process.

Minimal Core Language | Formal Specification

I believe for long term viability of Nitra some form of formal specification is needed. Once initial cut of Nitra iss out perhaps remove its dependency on Nemerle. Also perhaps Nitra can become a language of its own.

Some initial thoughts what should be there are:

  • HList / HMap based structures
    • Parameter lists are HLists, which are tuples
    • Objects are HMaps of Symbol and type to value or expression
  • Pattern matching
  • Formal specification of concurrency
  • Proofs
  • GADT
    • HOAS
  • Staging and macros
  • Macro based type inference (http://typedclojure.org/)
  • Embedded logic and relational programming (http://flix.github.io/, http://www.rascal-mpl.org/)
  • Tag types (type based capabilities, effects, annotation types, constraint types, phantom types, Substructural type)
  • Nominative and structural typing

This is a brain dump of the ideas:

Creating a symbol

def a // Type Any, Effects {Initializable}, Contains AnyRange, Scope current, etc.
def a = 1.0 // type float
a := a : int // converts value and binding of a to int and mutate
def a = 1.0
def b -< a // a is now unusable, b borrows value of a
b >- a // b is unusable, b gives back value to a 
def a @{Read}
a = 1 // = is only for initialize of 1st assignment
// a := 1 // error

def b @{Read, Write} = 1
b := b + 1
def a: [int @{len(> 10)}] // a is a list of int with a dimension greater than 10
def b: [@{len(> 10)}] // b is a HList with a dimension greater than 10
def c: [<: Number @{len(> 10)}] // c is a HList which contains subtype Number with a dimension greater than 10
def a = 1 -> 2
def b = a[1] // Given 1 return 2
def c = a // c = 1

def d = 1 -> 2 | 3 -> 4 // give 1 or 2 returns 2 or 4
def m: [A -> B] // HMap type A to B
def m: [A => B] // HList function from A to B
def a: Int | Float = 1.0 // int or float
def b: Mamel & Quadruped = dog // should satisfy both types
def a: @{value(1 | 2)} = 1 // a can hold 1 or 2
def a = (1 | 2) -> 'A' // a maps 1 and 2 to 'A'
def b = a[1]

type c = @{values(1 | 2)} // value as types
type c = 1 | 2 // same as above

// types can also be sets of values of values with ordering or partial ordering or unordered. How this is done needs to be thought thought.

type d = 'A'

def e = c -> a
def f = e[1] // same as b
def a = 1
def b = a: @{values((1|2|3) -> 'A' | (4|5|6) -> 'B')} // b is 1; pattern matching
def b = a: (1|2|3) -> 'A' | (4|5|6) -> 'B') // same as above

type c = @{values((1|2|3) -> 'A' | (4|5|6) -> 'B')}
type c = (1|2|3) -> 'A' | (4|5|6) -> 'B') // same as above
def d = a: c // same as b
def e = 1: c // same as b
type A {
  def a: int @{private(<: B)} // private in any subtype of B otherwise accessible in any type which is not a subtype of B
}
// Define type A

type B <: A { // B extends A
  def b: int
}
// B is a subclass of A with additional definition

type C: B // C is an alias for B

type D: B { ... } // D is nominatively considered as B though it has additional functionality. Essentially this is a subtype but D can be substituted where B is expected.

type S :> A {
  def s1: int,
  def init1: () => () @{new(_), init(s1)} = { s1 = 1 }, // When creating a new object run this function which initialises s1
  def s2: int,
  def init2: () => () @{new(_), init(s2, after = init1)} = { s2 = 2 }, // When creating a new object run this function which initialises s2 after init1 is run
  def s3: int,
  def init3: () => () @{new(_), init(s3)} = { s3 = 3 }, // can run in parallel to init1
}

type X<P> <: P // type X is subtype of  P

type Y<Q> = Q { ... } // Y is structure with elements of Q and { ... }
type Y1 = A { ... } // sames as above if Y<A>

type Z = { ... } // Z is a structural type

def s: {def f: int } // defining a structural type
def f: int => int = (a) => { ... } // function name followed by type and body
def f1 = (a) => { a.b } // find b in passed structure
def f2 = (a) => { a._: int } // find unknow symbol of type int in a

def b = 1

f1(_: int) // pass local scope as a record to the function, find all symbols of int type
f([_: int][0]) // pass local scope as a record to the function, find 1st symbols of int type
f([_: int]*.b) // pass local scope as a record to the function, find symbols b of int type
type A = { def f1 = 1 ... }
def b = .f1 // find binding f1

def a = new<A>

def c = a.b // same as a.f1 or in other pseudo language [a].map(_.f1)
def d = a.*[.f1(), .f2(), f3()] // get a list evoking all expression f1, f2 & f3 in a tuple / HList - [a].map((_.f1(), ...))
def e = [o1, o2, o3]*.f1() // for all object o1, o2m o3 evoke f1 getting a tuple - zip([o1]. ...).map(_.f1())
def f = [o1, o2, o3]*.*[.f1(), .f2(), f3()] // For all object in the 1st list evoke expression in the 2nd list getting a nested tuple zip(...).map(((_.f1(), ...), (_.f1(), ...), ...)
def f(a = _ : int) = a // find implicitly a int value
def f() = _: int // find implicitly a int value in scope
type t = int : 1 // dependent type 1
def a: int : 1 = 10 //
def b = a :: type // b is Any:1 
type x = a : ? // x is int
def c = a // c is 10
def d = _: ? : 1 // d is 10
type e = _ :: ? // e is Any:1

@{lazy} - lazy
@{strict} - strict

default is undefined so compiler can use strictness inference.

This is just a 1st impression dump of ideas. Perhaps we can how to refine this. Perhaps someone can take on the formalism part.

Option to disable semantic analysis in Visualizer

Currently the Visualizer runs the semantic analysis automatically.

When writing tests for a given language, it would be useful to disable semantic checks in a test suite. That way one can cover the full range of syntactic constructs more easily, since the content doesn't need to to adhere the semantic rules (e.g. references don't need to exist).

Syntax highlighting not applied with regex-rules using another regex-rule

The following grammar does not produce any syntax highlighting for the keywords FLOAT and INTEGER even though it should.

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;

    [StartRule]
    syntax Expressions = (Keyword sm IdentifierBody ';' nl)+;

    regex Keyword = Keyword_FLOAT | Keyword_INTEGER;

    [SpanClass(Keyword)] regex Keyword_FLOAT = "FLOAT";
    [SpanClass(Keyword)] regex Keyword_INTEGER = "INTEGER";
  }
}

As a workaround one must add [SpanClass(Keyword)] directly to regex Keyword which might not always be desirable.

AST: "as" pattern in "when"- and "unless"-clause does not bind to the variable

Despite being declared in the when-condition, the variable Foo1 is not actually visible and the compiler produces an error message. This happens with unless as well.

using Nitra;

namespace Test
{
  ast TestAst
  {
    when(Foo is Test.Foo as Foo1)
      Error(context, "Cannot be Foo(" + Foo1.Integer + "), must be Bar."); // error : unbound name `Foo1'

    out Foo : Test = Test.Foo(1);
  }

}
namespace Test
{
  public variant Test
  {
    | Foo { Integer : int;   }
    | Bar { Float   : float; }
  }
}

Is Nitra still usable?

Is Nitra still relevant?

I wanted to take a shot at learning how to use this, but I noticed it hasn't received update recently, is Nitra still a thing?

Warnnings when ast-type contains more than 32 elements

The following code produces three compiler warnings:

namespace Test.Ast
{
  ast Foo 
  {
    in Bar01 : Bar;
    in Bar02 : Bar;
    in Bar03 : Bar;
    in Bar04 : Bar;
    in Bar05 : Bar;
    in Bar06 : Bar;
    in Bar07 : Bar;
    in Bar08 : Bar;
    in Bar09 : Bar;
    in Bar10 : Bar;
    in Bar11 : Bar;
    in Bar12 : Bar;
    in Bar13 : Bar;
    in Bar14 : Bar;
    in Bar15 : Bar;
    in Bar16 : Bar;
    in Bar17 : Bar;
    in Bar18 : Bar;
    in Bar19 : Bar;
    in Bar20 : Bar;
    in Bar21 : Bar;
    in Bar22 : Bar;
    in Bar23 : Bar;
    in Bar24 : Bar;
    in Bar25 : Bar;
    in Bar26 : Bar;
    in Bar27 : Bar;
    in Bar28 : Bar;
    in Bar29 : Bar;
    in Bar30 : Bar;
    in Bar31 : Bar;
    in Bar32 : Bar;
    in Bar33 : Bar;
  }
  
  ast Bar {}
}
D:\<..>\Ast.nitra(1,1): warning : N10011: comparing values of types int and uint with reference equality
D:\<..>\Ast.nitra(6,7): warning : N10011: comparing values of types int and uint with reference equality
D:\<..>\Ast.nitra(6,7): warning : N10011: comparing values of types int and uint with reference equality

If at least one of the properties is commented out, the file compiles without warnings.

Since there are no comparisons happening in the code, this looks like a Nitra bug.

For the sake of simplicity I've only used properties in this example. I can't exactly say to which elements count towards the limit, but there are others too. The actual case where I encountered this had calls to some extensions methods (written in Nemerle), which counted as well.

AST: Cannot access property of an object

This code produces an compilation error:

namespace Test.Ast
{
  ast Foo 
  {
    in Test1 : string;
    in Test2 : string;
    in Test3 : string;

    Test1 = StringWrapper("Test").Attribute;
    Test2 = StringWrapper("Test").Method();
    Test3 = StringWrapper("Test").Property; // error : Unexpected expression 'Test.StringWrapper ("Test")' Call
  }
}

The string wrapper looks like this:

namespace Test
{
  [Record(Include=[Attribute])]
  class StringWrapper
  {
      public Attribute : string;
      
      public Property : string { get { Attribute } }
      
      public Method() : string
      {
          Attribute
      }
  }
}
  }
}

Compile error when declaring alias after usage

The following code produced the compiler-error error : Unbound name 'Bar':

namespace Test
{
  syntax module Test
  {
    using Nitra.Core;

    token Foo = "ASDF";

    token MultipleBar = Bar+;

    alias Bar = Foo;
  }
}

If I switch the rules MultipleBar and Bar everything works fine.

Custom Type Cohesions / Casting

Type cohesions is a very important area. Sometimes you need to convert from one type to another which does not have parent client relationship in the type hierarchy. E.g. XML format to JSON. In such cases provide a easy to use framework to do type casting.

This can be used in defining the language automatic casting and other casting rules also.

AST: Cannot use extension methods in interpolated strings

The compiler gives two error messages with this program:

using Nitra;
  
namespace Test
{
  ast Test
  {
    Error(context, "Extension methods inside interpolated strings don't work:");
    Error(context, $"$(Foo.UnboxAndIncrement())"); // error : there is no member named `UnboxAndIncrement' in Test.Foo with type ?
                                                   // error : typing fails on ambiguity between overloads: 
    Hint(context, $"This works fine: $(FooExtensions.UnboxAndIncrement(Foo))");
    
    in Foo : Foo = Foo(2);
  }
}
using System.Console;

namespace Test
{
  public module FooExtensions
  {
    public UnboxAndIncrement(this foo : Foo) : int
    {
      foo.Bar + 1;
    }
  }
  
  [Record]
  public class Foo
  {
    public Bar : int { get; }
  }
  
  public module FooTester
  {
    public Test(foo : Foo) : void
    {
      WriteLine($"This also works fine: $(foo.UnboxAndIncrement())");   
    }
  }
}

In addition to the error messages, I also get several hints about System.Convert.ToString() overloads.

Note that this is Nitra specific. As you can see from the WriteLine() in the last line of the second file, it works correctly in Nemerle.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.