HP Forums

Full Version: prefix notation and () on newRPL project
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi Claudio,

2 Crazy ideas =)

◉ Observing the u_LISP project that has a notation similar to the prefix notation, and that the R-PN is a inverse prefix.
So I "think" it's easy to add a second type of operation engine PN/prefix ("eliminate" the Reverse) or consult it in this community if they are involved in this type of notation in your project.


[Image: lispbadgehand.jpg]


(3+4) * (5-6) returns -7 // "infix" operation or what better should be called standard notation

*( +(3,4), -(5,6) ) prefix operation with ( )
* + 3 4 - 5 6 prefix operation

◉ A second idea, RPN with parentheses, this gives a faster interpretation of the source code

3 4 + 5 6 - * postfix operation
((3,4)+, (5,6)-)* postfix operation with ()


The importance of the use of parentheses is that each operator can operate on n arguments
(a,b,c)+ (a,b,c,d,e)-
(01-21-2019 05:06 PM)compsystems Wrote: [ -> ]Hi Claudio,

2 Crazy ideas =)

◉ Observing the u_LISP project that has a notation similar to the prefix notation, and that the R-PN is a inverse prefix.
So I "think" it's easy to add a second type of operation engine PN/prefix ("eliminate" the Reverse) or consult it in this community if they are involved in this type of notation in your project.

◉ A second idea, RPN with parentheses, this gives a faster interpretation of the source code

3 4 + 5 6 - * postfix operation
((3,4)+, (5,6)-)* postfix operation with ()

The importance of the use of parentheses is that each operator can operate on n arguments
(a,b,c)+ (a,b,c,d,e)-

While crazy, adding alternate syntax rules to RPL is possible and I'm considering an alternate language to the same code.
The idea is to compile code in other languages to an RPL stream. Decompiling is much more complex so it would probably have to keep the source code separate (like most compiled languages).
Lisp would be very straighforward: An opening parenthesis simply compiles as the start of a list '{', everything gets pushed to the stream until a closing parenthesis is found, which is compiled as an end of list '}'. Then parenthesis simply pushes the number of arguments, then does LIST-> ROLL EVAL to execute the first argument.

But rather than adding a language of similar difficulty as RPL, the idea is to add a much higher level language, like Lua or python.
Compiling these languages is very difficult, so I'm still studying this as a possibility, not saying I might do it.
(01-21-2019 05:51 PM)Claudio L. Wrote: [ -> ]Lisp would be very straightforward …

But rather than adding a language of similar difficulty as RPL, the idea is to add a much higher level language, like Lua or python.

Not sure if you are aware of the power of Lisp macros.

Cheers
Thomas
(01-21-2019 05:06 PM)compsystems Wrote: [ -> ]◉ Observing the u_LISP project that has a notation similar to the prefix notation, and that the R-PN is a inverse prefix.
So I "think" it's easy to add a second type of operation engine PN/prefix ("eliminate" the Reverse) or consult it in this community if they are involved in this type of notation in your project.

Infix or rpn macro is not hard, but you are better off stay with lisp syntax.
It does not take much time to get used to (* (+ 3 4) (- 5 6))

BTW, does u-lisp support macro ?

Quote:◉ A second idea, RPN with parentheses, this gives a faster interpretation of the source code
The importance of the use of parentheses is that each operator can operate on n arguments (a,b,c)+ (a,b,c,d,e)-

It might not run faster.
I never tried u-lisp, but with Chez scheme 7.4d, (+ a b c) is slower than (+ (+ a b) c)

Above assumed a,b,c are variables. With numbers, both form optimized to a single number.
(01-21-2019 06:17 PM)Thomas Klemm Wrote: [ -> ]Not sure if you are aware of the power of Lisp macros.

Cheers
Thomas

I wasn't. I did a lot of Lisp programming many years ago, but not on a general purpose Lisp. I used to code AutoLISP, the implementation used in AutoCAD. I have no idea if that implementation had macros (since AutoCAD has another syntax for macros called Diesel), and I never needed to use them anyway.
But it looks really powerful. Unfortunately, that's not what I was talking about in this thread, implementing macros is a whole different animal than just doing the basic syntax over the RPL execution engine.
(01-21-2019 05:51 PM)Claudio L. Wrote: [ -> ]But rather than adding a language of similar difficulty as RPL, the idea is to add a much higher level language, like Lua or python.
Compiling these languages is very difficult, so I'm still studying this as a possibility, not saying I might do it.

Python on my 50g would be quite incredible! List comprehension alone would make my day.

Hmm. How hard would it be to do list comprehension in newRPL? I'm guessing very, but I honestly have no real idea.

Syntax would be something like the bastard love-child of FOR/NEXT and SEQ.
(01-22-2019 03:06 PM)The Shadow Wrote: [ -> ]List comprehension alone would make my day.

What's wrong with SEQ?

Python

>>> [ x**2 + 1 for x in range(1, 11, 2) ]

[2, 10, 26, 50, 82]

Algebraic

'SQ(X)+1'
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }

Or using RPL

« X SQ 1 + »
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }


Kind regards
Thomas
Here is a *fast* rpn macro for Chez Scheme
Instead of using macro pattern matching, the code rearrange the list of syntax objects.

Code:
(define ^ expt)

(define (rpn-aux lst)
  (let scan ([e (cdr lst)] [x (car lst)] [s '()])
    (if (null? e)
      (if (null? s) x [cons* #'list x s]) ; return x or stack
        (case (syntax->datum (car e))
          ((+ - * / ^) (scan (cdr e) [list (car e) (car s) x] [cdr s]))
          ((@)         (scan (cdr e) [list x (car s)] [cdr s]))
          ((swap)      (scan (cdr e) [car s] [cons x (cdr s)]))
          ((dup)
            (if (atom? (syntax->datum x))
              (scan (cdr e) x [cons x s])
              (let ([dup (datum->syntax (car e) (gensym))])
                (list #'let (list (list dup x))
                  (scan (cdr e) dup [cons dup s])))))
          (else (scan (cdr e) [car e] [cons x s])))))) ; push data

(define-syntax (rpn stx)
  (syntax-case stx ()
    ((rpn x ...) (rpn-aux #'(x ...)))))

scheme> (load "rpn.ss")
scheme> (define phi (rpn 5 sqrt @ 1 + 2 /))
scheme> (define (fib n) (rpn phi n ^ 1 phi - n ^ - 5 sqrt @ /))
scheme> (fib 10)
55.000000000000014
scheme> (fib 20)
6765.000000000005
For completeness, this is my attempt for infix-to-prefix calc macro, for Chez Scheme

Note: the code scan tokens in reverse, from right to left.
This simplified code to use stack only for (* /)

(calc whatever +/- x) ⇒ (+/- (calc whatever) x)     ; unary ± has higher precedence than infix ±
(calc whatever x ^ y) ⇒ (calc whatever (^ x y))     ; ^ has associativity right to left

Code:
(define ^ expt)
(define calc-aux #f)
(let ()
  (define (calc-obj obj)
    (if (atom? (syntax->datum obj)) obj
        (calc-aux (syntax->list obj))))

  (define (1st e)  (calc-obj (car e)))
  (define (2nd e)  (calc-obj (cadr e)))
  (define (op e)   (syntax->datum (car e)))
  (define (process e)   (scan (cdr  e) (1st e) '()))
  (define (rest e) (scan (cddr e) (2nd e) '()))
  (define (do-term a term) [set-car! (cdr term) a] term)
  (define (build a term) [fold-left do-term a term])

  (define (scan e a term)      ; work with reversed expression e
    (if (null? e) (build a term)
      (case (op e)
        ((+ -)  (if (null? (cdr e))
                    (list (car e) (build a term))   ; unary +/-
                    (list (car e) [rest e] (build a term))))
        ((* /)  (scan (cddr e) (2nd e) [cons [list (car e) #f a] term]))
        ((^)    (scan (cddr e) [list (car e) (2nd e) a] term))
        (else   (scan (cdr  e) (1st e) [cons [list #'* #f a] term])))))

  (set! calc-aux
    (lambda (e)
      (if (eq? (op e) '@)
        (cdr e)               ; (@ func ...) -> (func ...)
        (process (reverse e))))))

(define-syntax (calc stx)
  (syntax-case stx () 
    ((calc a ...) (calc-aux #'(a ...)))))

scheme> (load "calc.ss")
scheme> (calc - 2 ^ 3 ^ 4)     ; = - (2 ^ (3 ^ 4))
-2417851639229258349412352
scheme> (calc - (2 ^ 3) ^ 4)
-4096

scheme> (calc 1 + 2 3 4)       ; implied multiply
25
scheme> (define (calc-expand s) (syntax->datum (calc-aux (syntax->list s))))
scheme> (calc-expand #'(1 + 2 3 4))
(+ 1 (* (* 2 3) 4))

scheme> (define phi (calc (1 + (@ sqrt 5)) / 2))
scheme> (define (fib n) (calc (phi ^ n - (1 - phi) ^ n) / (@ sqrt 5)))
scheme> (fib 10)
55.000000000000014
scheme> (fib 20)
6765.000000000005

calc macro had unary (+ -) between binary (* /) and (+ -), similar to Fortran 77
see http://macnauchtan.com/pub/precedence.html#_Fortran
Reference URL's