Coder Social home page Coder Social logo

nanopass-framework-racket's People

Contributors

akeep avatar eholk avatar leifandersen 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

nanopass-framework-racket's Issues

feat: clarify default parameters for passes

I think we can use default values for extra formal parameters in the define-pass form:

(define-pass name : lang-specifier (formal ...) -> lang-specifier (extra-return-val ...)
  definitions-clause
  processor ...
  body-expr)

And the following code works:

(define-language L
  (entry Expr)
  (terminals
   (number (n)))
  (Expr (e)
        n
        (someop e)))
(define-parser parse-L L)

(define-pass as-bin : L (ir global-ctx) -> L ()
  ( as-binary : Expr (ir [ctx global-ctx]) -> Expr ()
              [,n (modulo n 2)]
              [(someop ,[e? 'val-b -> e]) `(someop ,e)]))
; usage:
; (as-bin (parse-L '(someop 4)) 'val-default)
; or
; ((compose (curryr as-bin 'val-default) parse-L) '(someop 4))

But only the processor as-binary can have the default value, and I think It would be cool to be able to also write default values as the define statement does:

;                           ⬐---------here---------⬎
(define-pass as-bin : L (ir [global-ctx 'val-default]) -> L ()
  ( as-binary : Expr (ir [ctx global-ctx]) -> Expr ()
              [,n (modulo n 2)]
              [(someop ,[e? 'val-b -> e]) `(someop ,e)]))

; suggested usage:
; (as-bin (parse-L '(someop 4)))
; or
; ((compose as-bin parse-L) '(someop 4))

Note

The documentation does not say anything about default parameters:

formal is an identifier representing a formal argument.

Internal error from make-language

The following program gives the error:

../../Applications/Racket v6.2/collects/racket/contract/private/blame.rkt:143:0: make-language: contract violation
expected: identifier?
given: #f
in: the 2nd argument of
(->
identifier?
identifier?
(listof tspec?)
(listof ntspec?)
language?)
contract from:
/nanopass-framework-racket/private/records.rkt
blaming: /nanopass-framework-racket/private/language.rkt
(assuming the contract is correct)
at: /nanopass-framework-racket/private/records.rkt:65.5

#lang nanopass
(define variable? symbol?)

(define-language L
  (entry Expr)
  (terminals
   (variable (x)))
  (Expr (e)
    x))

(define-language L1
  (terminals
   (+ (variable l))))

Internal error: private/records.rkt:465:43: unique-symbol: contract violation

lang nanopass

(define-language Lsrc
(entry Expr)
(terminals
(symbol (x))
(syntax (s)))

(Binding (b)
[(x ...) e])

(Expr (e)
x
(let-values s (b ...) e0 e1 ...)))

Dropbox/GitHub/nanopass-framework-racket/private/records.rkt:465:43: unique-symbol: contract violation
expected: identifier?
given: #<syntax:9:5 (x ...)>
in: an element of
the rest argument of
(->*
(identifier?)
#:rest
(listof identifier?)
symbol?)
contract from:
/nanopass-framework-racket/private/helpers.rkt
blaming: /nanopass-framework-racket/private/records.rkt
(assuming the contract is correct)
at: /nanopass-framework-racket/private/helpers.rkt:34.5

Internal Error (Output nonterminal for pass transformation is unbound)

In the program below Foo is not bound as a nonterminal.
The program provokes an internal error rather than "Error: Foo is not defined as a nonterminal".

lang nanopass

(define-language Lsrc
(entry Expr)
(terminals
(symbol (x)))

(Expr (e)
x))

(define-pass parse : * (stx) -> Lsrc ()
(definitions)

(foo : * (E) -> Foo ()
`,'t)

(foo stx))

Bug in handling of catamorphism in define pass

The following program gives the error:

nanopass-framework-racket/private/meta-parser.rkt:243:27: tspec-type: broke its contract
  promised: identifier?
  produced: 'symbol
  in: the range of
      (-> tspec? identifier?)
  contract from: 
      <pkgs>/nanopass-framework-racket/private/records.rkt
  blaming: <pkgs>/nanopass-framework-racket/private/records.rkt
   (assuming the contract is correct)
  at: <pkgs>/nanopass-framework-racket/private/records.rkt:76.5

/Jens Axek

#lang nanopass

(define-language L
  (entry Expr)
  (terminals
   (symbol (x)))
  (Expr (e)
    x
    (x ...)))

(define-language L1 (extends L)
  (Expr (e)
    (+ (call e0 ...)  => (e0 ...))))

(define (parse s)
  (with-output-language (L Expr)
    (cond
      [(symbol? s) `,s]
      [(list? s)   `(,s ...)]
      [else (error)])))

(define-pass pass1 : L (E) -> L1 ()
  (definitions)
  (Expr : Expr (E) -> Expr ()
    [(,[x] ...) `(call ,x ...)]))

(unparse-L1
 (pass1
  (parse '(x y z))))

Support for DrRacket arrows and renaming

After syntax checking DrRacket supports some nice features:

  • Hovering over an identifier shows an arrow to its binding
  • Rightclicking an identifier allows (lexical scope aware) renaming of identifiers
    All identifiers with the same binding are renamed.

Consider this program:

#lang nanopass
(define-language L
  (entry Expr)
  (terminals (number (r)))
  (Expr (e) r))

(with-output-language (L Expr) 1)

I would like to rename L but the renaming option is not available.
In order to support renaming one has to add properties:

http://docs.racket-lang.org/tools/Check_Syntax.html?q=sub-binder#%28idx._%28gentag._28._%28lib._scribblings%2Ftools%2Ftools..scrbl%29%29%29

Note that if the property 'sub-range-binders is used then a renaming of L to M
will also rename unparse-L to the unparse-M.

Wrong error (define-pass)

Same problem as the previous issue. Here L is unknown, but an internal error is given.

lang nanopass

(define-pass pass1 : * (s-exp) -> L ()
42)

Templates with literal ... produces an internal error

The following

(Expr : Expr (e dest) -> Expr ()
[(let-values ,s (((,x ...) ,ce) ...) ,e)
; todo handle multiple values
(let* ([x0 (map first x)] [ce (map CExpr ce x0)] [e (Expr e)])
`(let ([,x0 "undefined"] ...)
(body ,ce ... ,e)))])

produces the error

../../nanopass-framework-racket/private/meta-parser.rkt:415:39: cadr: contract violation
  expected: (cons/c any/c pair?)
  given: #<syntax (quote "undefined")>

The error ought should be an external error - not an internal one.

Internal error from forgotten unquote

The following program provokes an internal error, rather than signaling one the user program.

lang nanopass

(define-language L
(terminals (symbol (x)))
(term (t) x))

(define x 42)

(define-pass pass1 : L (t) -> * ()
(term : term (t) -> * ()
[x "it is a symbol"]))

The error is:

Dropbox/GitHub/nanopass-framework-racket/private/pass.rkt:319:33: nano-meta-fields: contract violation
expected: nano-meta?
given: '#s(nano-quote #<syntax (quote x)>)
in: the 1st argument of
(->
nano-meta?
(listof
(or/c
nano-dots?
nano-quote?
nano-unquote?
nano-cata?
nano-meta?
(listof any/c))))
contract from:
/nanopass-framework-racket/private/records.rkt
blaming: /nanopass-framework-racket/private/pass.rkt
(assuming the contract is correct)
at: /nanopass-framework-racket/private/records.rkt:44.5

Improve error message for default nanopass-case message

When nanopass-case is called with a value V that no clauses match and there is no default else-clause the error message doesn't show the value V. The entire form is printed. Note that the DrRacket seems to color more than the nanopass-case expression red - which suggest that the source location is not correct.

Example of error message:

nanopass-case: empty else clause hit (nanopass-case (LFE2 GeneralTopLevelForm) T 
((unquote e) (Expr e id)) ((define-values (unquote s) ((unquote x) ...) (unquote e)) 
(quasiquote (define-values (unquote s) ((unquote x) ...) (unquote (RHS e id))))) 
((define-syntaxes (unquote s) ((unquote x) ...) (unquote e)) (quasiquote (define-syntaxes 
(unquote s) ((unquote x) ...) (unquote (RHS e id)))))) 
<pkgs>/nodejs/nodejs/compiler.rkt:804.6

Internal error

The program below gives the following internal error:

nanopass-framework-racket/private/records.rkt:467:52: car: contract violation
  expected: pair?
  given: 1

#lang nanopass
(define-language L
  (terminals
   (symbol (x)))
  (entry Expr)
  (Expr (e)
    (1 2)
    (e0 e1)))

nanopass-case producing unexpected error

(originally submitted over email to the nanopass-framework mailing list by Axel Søgaard)

The following programs compiles without errors:

lang nanopass

(define variable? symbol?)

(define-language LFE
(entry TopLevelForm)
(terminals
(variable (x xd)))
(Formals (f) x)
(TopLevelForm (t) g)
(GeneralTopLevelForm (g) e)
(Expr (e) x))

(define-language LFE2 (extends LFE)
(Abstraction (ab)
(+ (λ f e) => (λ f e)))
(Expr (e)
(+ ab)))

(define-language LANF (extends LFE2)
(AExpr (ae)
(+ x
ab))
(CExpr (ce)
(+ ae))
(Expr (e)
(+ ae
ce)))

However, if I add the following expression, I get an error:

(λ()
(nanopass-case (LANF Expr) 43
[else 4]))

The (internal) compile time error I get is:

Dropbox/GitHub/nanopass-framework-racket/private/pass.rkt:1059:52: memf: not a proper list: '#s((nonterminal-alt #(0) alt 3) #<syntax:27:7 ae> #f #f #<syntax:21:3 AExpr>)

I know that 43 isn't an LANF Expression, but that's besides the point.

Note that if I change

(Expr (e)
(+ ae
ce)))

to

(Expr (e)
(+
ce)))

the error disappears.

Is the language definition correct?

Internal error when language not defined in define-pass

This program provokes an internal error:

lang nanopass

(define-pass categorize-applications : L0 (Expr) -> L1 ()
(definitions)
(Expr : Expr (E) -> Expr ()))

Dropbox/GitHub/nanopass-framework-racket/private/pass.rkt:1440:33: syntax-local-value: not defined as syntax identifier: #<syntax:3:39 L0>

A better error would be:

L0 is not defined as a nanopass language (using define-language)

Internal error from tspec-pred

I ran into this error:

../../nanopass-framework-racket/private/pass.rkt:1188:42: tspec-pred: contract violation
expected: tspec?
given: #f
in: the 1st argument of
(-> tspec? (or/c #f identifier?))
contract from:
/nanopass-framework-racket/private/records.rkt
blaming: /nanopass-framework-racket/private/pass.rkt
(assuming the contract is correct)
at: /nanopass-framework-racket/private/records.rkt:79.5

Wrong error

The following program gives an internal error.
A better error message would be:
"Lsrc is not defined as a language"
Also the source location for the error should be Lsrc.

lang nanopass

(define-language L1 (extends Lsrc)
(Expr (e) (- (if e0 e1))))

The current error:

nanopass-framework-racket/private/language.rkt:242:31: syntax-local-value: not defined as syntax
identifier: #<syntax:3:29 Lsrc>

Improve error message

This program gives the error "define-language: unrecognized clause in: (Expr r)".
Better wording:
"define-language: Expected nonterminal clause of the form
(keyword (meta-var ...) production-clause ...) in: (Expr r).

(define-language L
(entry Expr)
(terminals (number (r)))
(Expr r))

Wrong source location of error

The following error typically occurs when an attempt to construct a nonterminal fails due
to the wrong type of a field value:

box-mutables: expected Expr but received 
(let-values #<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:517:16 ac> 
(((((#(struct:variable #<syntax x.1>))) ...) ((app 
#<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:517:16 ac> 
#(struct:variable #<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:520:33 box>) 
(quote #<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:517:16 ac> 
#(struct:datum #<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:517:16 ac> 
-42))))) ...) #(struct:LFE1:app:Expr.43 91 
#<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:517:16 ac> 
#(struct:variable #<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:519:33 
set-box!>) (#(struct:variable #<syntax x.1>) #(struct:LFE1:quote:Expr.40 67 
#<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:587:34 (quote 2)> 
#(struct:datum #<syntax:/Users/soegaard/Dropbox/GitHub/nodejs/nodejs/compiler.rkt:587:34 
(quote 2)> 2))))) in field e of (λ s f e) from expression (LambdaBody s f (formal-variables f) e) 
<pkgs>/nodejs/nodejs/compiler.rkt:563.35

Notice that the important bit is at the very end:

in field e of (λ s f e) from expression (LambdaBody s f (formal-variables f) e) 
< pkgs>/nodejs/nodejs/compiler.rkt:563.35

The location of the error is correct here: line 563.

The expression colored red in DrRacket is the last expression of the define-pass form
in which the (λ ,s ,f ,e) template appears however. [This is the issue reported].

Also note that the error begins with:

   box-mutables: expected Expr but received 

which tricks one to believe the problem lies somewhere where box-mutables is called with the wront type of argument. Maybe it were a good idea to move the last bit to the top?

nanopass-case

This may or may not be a bug in nanopass-case.
If there were a nanopass-mailing list I would tried there before filing an issue.

This works:

 (let ([M (parse '((λ (x) x) 4))])
    (nanopass-case (LCS Term) M
       [(call ,M ,M1 ...) (list 'call M M1)]
      [else  'huh]))

But this

(let ([M (parse '(let (y 5) 6))])
    (nanopass-case (LCS Term) M
      [(let (,x ,M) ,M1 ...) (list M M1)]
      [else  'huh]))

gives the error:

define-pass: quoted terminals currently unsupported in match patterns in: (quote let)

The problem is that let is defined as a non-terminal of Term in the language LCS.
I.e. it is not a quoted terminal.

Am I using nanopass-case in the wrong way, or is there a bug?

The entire program is here:

https://gist.github.com/soegaard/b52cb97f65c608251d60

Wrong `begin` form.

This may not be solvable (or may require backtracking when constructing language). But I'll put this here anyway, and if it's not doable, we should output a better error message.

Let's say I have the following language;

#lang nanopass
(define-language Lsrc
  (terminals
   (symbol (s))
   (number (n)))
  (stmt (stmt)
        n
        expr
        (begin stmt ...))
  (expr (expr)
        s
        (begin expr ...)))

I cannot construct the following grammar:

(with-output-language (Lsrc stmt)
  `(begin a 5))

Because it tries to use the expr begin, rather then stmt's. (Which is understandable because an expr is a valid stmt.

So, this makes me think either we need to improve the pattern matcher to allow this, and at least try to pick the right one (if it exists anyway), or if I give an ambiguous grammar, give that as an error message.

Wrong error

The following program gives an error not in the user program but in the framework.

lang nanopass

(define (constant? c)
(number? c))

(define-language L
(terminals
(constant (c)))
(Expr (e)
c))

(define (parse v)
(with-output-language (L Expr)
(cond
[(number? v) `,v]
[else (error 'parse "got: ~a" v)])))

(define-pass add1 : L (e) -> L ()
(Expr : Expr (e) -> Expr ()
[c (guard (even? c)) (+ c 1)]))

(add1 (parse 42))

The mistake made above is that [c (guard (even? c)) (+ c 1)] should have been [,c (guard (even? c)) (+ c 1)].

The error message given is shown below. It indicates an internal error.

Dropbox/GitHub/nanopass-framework-racket/private/pass.rkt:319:33: nano-meta-fields: contract violation
expected: nano-meta?
given: '#s(nano-quote #<syntax (quote c)>)
in: the 1st argument of
(->
nano-meta?
(listof
(or/c
nano-dots?
nano-quote?
nano-unquote?
nano-cata?
nano-meta?
(listof any/c))))
contract from:
/nanopass-framework-racket/private/records.rkt
blaming: /nanopass-framework-racket/private/pass.rkt
(assuming the contract is correct)
at: /nanopass-framework-racket/private/records.rkt:44.5

Errors from with-output-language

Here are two examples of problematic errors from with-output-language:

#lang nanopass
(define-language L
  (entry Expr)
  (terminals
   (symbol (s)))
  (Expr (e) s))

(with-output-language (L Foo)
  `,3)

This first example gives there error

Dropbox/GitHub/nanopass-framework-racket/private/meta-parser.rkt:361:4: L: unrecognized nonterminal passed to meta parser Foo

But the error location is missing (Foo is not colored red).

The next example shows a missing error:

#lang nanopass
(define-language L
  (entry Expr)
  (terminals
   (symbol (s)))
  (Expr (e) s))
  (with-output-language (L Foo)
    3)

Compiles without errors. I expected to get the error: "Foo is not a nonterminal in L"

Improve error and location when "duplicate alt" is detected

The following program provokes an "duplicate alt" error.
I suggest that the error location becomes (+ s).

The current error.
define-language: duplicate alt in add in: #s((terminal-alt #(0) alt 3) #<syntax:12:7 s> #f #f #f)

Could this message be improved?

#lang nanopass

(define-language L
  (entry e)
  (terminals
   (symbol (s)))
  (Expr (e)
    s))

(define-language L1 (extends L)
  (Expr (e)
    (+ s)))

Errors in (error ...) usage

It seems that the Chez Scheme error procedure use a different convention than Racket.

Racket expects the following: (error src format-string v ...)
If there are no ~a (or similar) in the format string then an error will throw an error if there are any additional arguments present.

Below is a list of places where I think there could be problems.
The list is an edited version of the output of

grep -A3 "(error" *.rkt > errors.txt

run in nanopass-framework-racket/private/

helpers.rkt: (error who "invalid optimization level" n))

language-node-counter.rkt: [else (error '#,proc-name "unrecognized term" x)]))

language-node-counter.rkt: [else (error 'name "unrecognized language record" x)])))))))))])))

parser.rkt: [else (error who "expected to find matching tspec" alt)])])

parser.rkt: (error (if trace? 'trace-define-syntax 'define-syntax)

parser.rkt- "invalid language identifier" lang))

pass-helper.rkt: [else (error 'syntax->datum-helper "unexpected type" stx)])))]))

pass.rkt: [else (error who "unrecognized nano-rec" nrec)])))

pass.rkt: [(terminal-alt? in-altrec) (error who "unexpected terminal alt" in-altrec)]

pass.rkt: [(nonterminal-alt? in-altrec) (error who "unexpected nonterminal alt" in-altrec)])))

pass.rkt: (unless (list? ls) (error 'who "not a proper list" ls))

pass.rkt: (error 'who "mismatched list lengths" ls1 ls2 ...)))

pass.rkt: #`(error '#,(pass-desc-name pass-desc)
pass.rkt- #,(format "unexpected ~s" (maybe-syntax->datum itype))

pass.rkt- #,fml))])))

pass.rkt: #`(error '#,(pass-desc-name pass-desc)
pass.rkt- #,(format "unexpected ~s" (maybe-syntax->datum itype))

pass.rkt- #,fml))]))]))))))))))

records.rkt: [else (error who "unexpected alt" alt)])))

records.rkt: [else (error who "unrecognized type" x)])))

records.rkt: [else (error who "unrecognized type" x)])))

records.rkt: [else (error who "unexpected alt" ialt)]))))

unparser.rkt: [else (error who "invalid record" ir)]))))))

unparser.rkt: [else (error '#,name
unparser.rkt- "unrecognized language record"
unparser.rkt- ir)])])))))))

Wrong source location for error

The following program uses the same variable twice.
The error is correct, but I expected DrRacket to highlight the second e in the definitions window.

lang nanopass

(define (constant? c)
(number? c))

(define-language L
(terminals
(constant (c)))
(Expr (e)
c
(if e e)))

Internal error (forgotten ~a in error message)

The following program gives this error:
error: format string requires 0 arguments, given 1; arguments were: 'unparse-L2 "unrecognized language record" (L1:foo:Term.2 2 'a)

lang nanopass

(define-language L1
(terminals (symbol (x)))
(Term (M)
(foo x)))

(define-language L2
(terminals (symbol (x)))
(Term (M)
(foo x)))

(unparse-L2 (with-output-language (L1 Term) `(foo a)))

Improve error

The following program simply reports bad syntax, but the error location is lost.

lang nanopass

(define-language L1
(terminals (symbol x))
(Term (M)
x))

Wrong error location

In the following program I expect DrRacket to color the t red.

(define-language L
  (entry e)
  (terminals (symbol (s)))
  (Expr (e)
    (s ...) => (t ...)))

Also note that the error is worded in terms of extended-quasiquote and not define-language.

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.