On Sun, Apr 12, 2020 at 08:09:46AM +0200, Tomas Hlavaty wrote:
> Rowan Thorpe <ro...@rowanthorpe.com> writes:
> > parentheses are not used because as is stated at
> > https://picolisp.com/wiki/?src64 "Assembly language is not a
> > functional language, i.e. the individual instructions do not "return"
> > a value. So a fully parenthesized syntax is useless and just tedious."
> 
> because picolisp doesn't have a compiler (program)
> 
> it is "compiled" to the picolisp assembly manually ahead of time by Alex
> (human)

Actually, all this will change with the new PicoLisp "pil21". It is no longer
oriented to machine *instructions* like pil64, but to SSA (Static Single
Assignment) *values*.

It is a radically different approach. If there is interest, work in progress can
be seen at

   https://git.envs.net/mpech/pil21

or directly in

   https://software-lab.de/pil21.tgz

Here the sources have real PicoLisp syntax (though partially different
semantics). The compiler (in "src/lib/llvm.l") does not only use the reader, but
generates the LLVM-IR by *executing* the code (Forth is chuckling from behind).

This works by simply redefining some (not many) functions in llvm' and 'priv'
namespaces.


For example, the source of the 'car' function:

In pil64 it is (in "src64/subr.l")

   # (car 'var) -> any
   (code 'doCar 2)
      push X
      ld X E
      ld E ((E CDR))  # Get arg
      eval
      num E  # Need variable
      jnz varErrEX
      ld E (E)  # Take CAR
      pop X
      ret

This results in e.g. AMD/Intel asssembly (in "src64/x86-64.linux.base.s")

      .globl  doCar
   doCar:
      push     %r13
      mov      %rbx, %r13
      mov      8(%rbx), %r10
      mov      (%r10), %rbx
      test     $0x06, %bl
      jnz      1f
      test     $0x08, %bl
      cmovnzq  (%rbx), %rbx
      jnz      1f
      call     evListE_E
   1:
      testb    $0x06, %bl
      jnz      varErrEX
      mov      (%rbx), %rbx
      pop      %r13
      ret


Now in pil21 the source is (in "src/subr.l"):

   # (car 'var) -> any
   (de _car (Exe)
      (car (needVar Exe (eval (cadr Exe)))) )

and the result in LLVM-IR is (in "src/base.ll"):

   define i64 @_car(i64) {
   $1:
   ; # (cadr Exe)
     %1 = inttoptr i64 %0 to i64*
     %2 = getelementptr i64, i64* %1, i32 1
     %3 = load i64, i64* %2
     %4 = inttoptr i64 %3 to i64*
     %5 = load i64, i64* %4
   ; # (eval (cadr Exe))
     %6 = and i64 %5, 6
     %7 = icmp ne i64 %6, 0
     br i1 %7, label %$4, label %$3
   $4:
     br label %$2
   $3:
     %8 = and i64 %5, 8
     %9 = icmp ne i64 %8, 0
     br i1 %9, label %$6, label %$5
   $6:
     %10 = inttoptr i64 %5 to i64*
     %11 = load i64, i64* %10
     br label %$2
   $5:
     %12 = call i64 @evList(i64 %5)
     br label %$2
   $2:
     %13 = phi i64 [%5, %$4], [%11, %$6], [%12, %$5] ; # ->
   ; # (needVar Exe (eval (cadr Exe)))
     %14 = and i64 %13, 6
     %15 = icmp ne i64 %14, 0
     br i1 %15, label %$7, label %$8
   $7:
     call void @varErr(i64 %0, i64 %13)
     unreachable
   $8:
   ; # (car (needVar Exe (eval (cadr Exe))))
     %16 = inttoptr i64 %13 to i64*
     %17 = load i64, i64* %16
     ret i64 %17
   }

Looks unbelievably horrible, but works ;)

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to