public inbox for kawa@sourceware.org
 help / color / mirror / Atom feed
* no class-of ?
@ 2017-09-21 11:11 Sonny To
  2017-09-21 15:24 ` Per Bothner
  0 siblings, 1 reply; 10+ messages in thread
From: Sonny To @ 2017-09-21 11:11 UTC (permalink / raw)
  To: Kawa mailing list

there seems to be class-of function to get the type of the r-value of a symbol.

I'm not familiar with with the standard libraries of scheme and i'm
googling to get documentation and find various scheme documentation
from mit-scheme/racket/guile but are not available in kawa.

Is there a place where I can find a list of functions built into kawa?

thanks,
sonny

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-21 11:11 no class-of ? Sonny To
@ 2017-09-21 15:24 ` Per Bothner
  2017-09-22 18:29   ` Jamison Hope
  0 siblings, 1 reply; 10+ messages in thread
From: Per Bothner @ 2017-09-21 15:24 UTC (permalink / raw)
  To: Sonny To, Kawa mailing list

On 09/21/2017 04:11 AM, Sonny To wrote:
> there seems to be class-of function to get the type of the r-value of a symbol.

You can use the Java getClass method:
   (VALUE:getClass)
or:
   (invoke VALUE 'getClass)
or the "property" short-hand:
   VALUE:class

> I'm not familiar with with the standard libraries of scheme and i'm
> googling to get documentation and find various scheme documentation
> from mit-scheme/racket/guile but are not available in kawa.
> 
> Is there a place where I can find a list of functions built into kawa?

The Kawa manual attempts to document all the Kawa functions.
In the past I concentrated on documenting only Kawa extensions/differences
from standard Scheme (so you needed to also have a copy of R5RS/R7RS), but
I'm gradually making the Kawa manual more complete and self-contained.
(There may still be some R7RS procedures missing, though.)

There are also some implemented SRFIs, not all of which are fully documented
in the Kawa manual.  See:
   https://www.gnu.org/software/kawa/Implemented-SRFIs.html

Of course all of the Java APIs are always available, by using Java
method calls:
   https://docs.oracle.com/javase/8/docs/api/overview-summary.html
That is where you will find getClass documented:
   https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#getClass--
(the final '--' in the URL seems to be needed.)
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-21 15:24 ` Per Bothner
@ 2017-09-22 18:29   ` Jamison Hope
  2017-09-22 19:23     ` Per Bothner
  0 siblings, 1 reply; 10+ messages in thread
From: Jamison Hope @ 2017-09-22 18:29 UTC (permalink / raw)
  To: Kawa mailing list

On a somewhat related note, is there a way to define a macro that can
determine the type of an expression at macro expansion time, without
actually evaluating the expression?

I'd like to be able to do something along the lines of:


(define-syntax (ensure-boolean form)
  (syntax-case form ()
    ((_ expr)
     (let ((the-type (???? #'expr)))
       (cond ((eq? the-type boolean) #'expr)
             ((eq? the-type void)    #'(begin expr #t))
             ((eq? the-type int)     #'(= expr 0))
             (else (syntax-error "unsupported expression type")))))))


to be used as in:

(define (f x::double) ::boolean ...)
(define (g) ::int ...)
(define (h) ::void ...)

(list (ensure-boolean (let ((x 1.0)) (f x)))
      (ensure-boolean (g))
      (ensure-boolean (h)))

=>

(list (let ((x 1.0)) (f x))
      (= (g) 0)
      (begin (h) #t))

> On Sep 21, 2017, at 11:23 AM, Per Bothner <per@bothner.com> wrote:
> 
> On 09/21/2017 04:11 AM, Sonny To wrote:
>> there seems to be class-of function to get the type of the r-value of a symbol.
> 
> You can use the Java getClass method:
>  (VALUE:getClass)
> or:
>  (invoke VALUE 'getClass)
> or the "property" short-hand:
>  VALUE:class
> 
>> I'm not familiar with with the standard libraries of scheme and i'm
>> googling to get documentation and find various scheme documentation
>> from mit-scheme/racket/guile but are not available in kawa.
>> Is there a place where I can find a list of functions built into kawa?
> 
> The Kawa manual attempts to document all the Kawa functions.
> In the past I concentrated on documenting only Kawa extensions/differences
> from standard Scheme (so you needed to also have a copy of R5RS/R7RS), but
> I'm gradually making the Kawa manual more complete and self-contained.
> (There may still be some R7RS procedures missing, though.)
> 
> There are also some implemented SRFIs, not all of which are fully documented
> in the Kawa manual.  See:
>  https://www.gnu.org/software/kawa/Implemented-SRFIs.html
> 
> Of course all of the Java APIs are always available, by using Java
> method calls:
>  https://docs.oracle.com/javase/8/docs/api/overview-summary.html
> That is where you will find getClass documented:
>  https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#getClass--
> (the final '--' in the URL seems to be needed.)
> -- 
> 	--Per Bothner
> per@bothner.com   http://per.bothner.com/

--
Jamison Hope
The PTR Group
www.theptrgroup.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-22 18:29   ` Jamison Hope
@ 2017-09-22 19:23     ` Per Bothner
  2017-09-22 22:18       ` Jamison Hope
  0 siblings, 1 reply; 10+ messages in thread
From: Per Bothner @ 2017-09-22 19:23 UTC (permalink / raw)
  To: kawa

On 09/22/2017 11:28 AM, Jamison Hope wrote:
> On a somewhat related note, is there a way to define a macro that can
> determine the type of an expression at macro expansion time, without
> actually evaluating the expression?

Note that expressions do not have types at macro-expansion time - that happens
at a later stage.

What you can do is write a procedure and associate either a 'validate'
or a 'compile' property with it.

There are lots of examples in kawa/lib.  Look for the search string 'validate-apply:'.
For example in characters.scm:

(define (char->integer ch::character) ::int
   validate-apply: "kawa.lib.compile_misc:charToIntegerValidateApply"
   (as int ch))

You'll find charToIntegerValidateApply in compile-misc.scm:

(define-validate charToIntegerValidateApply (exp required proc)
   ((exp:isSimple 1 1)
    (let ((e0 (visit-exp (exp:getArg 0) character)))
      (apply-exp as int
                 (apply-exp gnu.kawa.functions.Convert:cast character e0)))))

This mean is exp is a simple application (no splices or keywords) with one argument,
then apply the following transformation.  This is evaluated during the
InlineCall phase of the compilation.

When it comes to charToIntegerValidateApply it first "validates" argument 0
in the context of the "required type" character (which is a 32-bit "primitive"
character type).  It then wraps the result in a call to the low-lever Convert:cast
procedure.  Assuming the types are correct, this will be a no-op.
Then that result is cast to an int.

If all goes well and the incoming value is a 32-bit unboxed character or a 16-bit unboxed char,
no code actually needs to be generated - which is the reason
for using the charToIntegerValidateApply transformer in the first place.  Otherwise,
you either get a compile-time error of the appropriate run-time conversion.

You can use (exp:getType) to get the type of the expression.

There is also the compile-apply property:

(define (values #!rest (args :: <Object[]>))
   validate-apply: "kawa.lib.compile_misc:valuesValidateApply"
   compile-apply: "kawa.lib.compile_misc:valuesCompile"
   (invoke-static <gnu.mapping.Values> 'make args))

This causes the valuesCompile method in class kawa.lib.compile_misc
to be called at code-generation time.  This is more low-level,
and most of the code-generation are actually written in Java to
generate custom byte-code depending on the argument expressions
and their types.

(If I wanted to get the type of a standalone expression, I'd
look at the implementation of eval (see kawa/lang/Eval.java), and do the same,
but stop before code-generation.  Specifically,you would probably want to do
compilation.process(Compilation.WALKED). Then you'd do something like
compilation.getModule().body.getType().

However, that doesn't give you the type on an expression *in a lexical context*.)
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-22 19:23     ` Per Bothner
@ 2017-09-22 22:18       ` Jamison Hope
  2017-09-22 22:26         ` Per Bothner
  0 siblings, 1 reply; 10+ messages in thread
From: Jamison Hope @ 2017-09-22 22:18 UTC (permalink / raw)
  To: Kawa mailing list

OK, so if I understand correctly, I can't use a macro for this, but what
I can do instead is write a function that always gets inlined.  The
function itself doesn't really have to do anything, because the real
work will be done in the validate-apply handler that rewrites the
procedure application to a new Expression.  And there, I can decide what
kind of Expression to construct based upon the Type of the argument
expression.

I think that should work for what I'm trying to accomplish, thanks!

-J

On Sep 22, 2017, at 3:21 PM, Per Bothner <per@bothner.com> wrote:
> 
> On 09/22/2017 11:28 AM, Jamison Hope wrote:
>> On a somewhat related note, is there a way to define a macro that can
>> determine the type of an expression at macro expansion time, without
>> actually evaluating the expression?
> 
> Note that expressions do not have types at macro-expansion time - that happens
> at a later stage.
> 
> What you can do is write a procedure and associate either a 'validate'
> or a 'compile' property with it.
> 
> There are lots of examples in kawa/lib.  Look for the search string 'validate-apply:'.
> For example in characters.scm:
> 
> (define (char->integer ch::character) ::int
>  validate-apply: "kawa.lib.compile_misc:charToIntegerValidateApply"
>  (as int ch))
> 
> You'll find charToIntegerValidateApply in compile-misc.scm:
> 
> (define-validate charToIntegerValidateApply (exp required proc)
>  ((exp:isSimple 1 1)
>   (let ((e0 (visit-exp (exp:getArg 0) character)))
>     (apply-exp as int
>                (apply-exp gnu.kawa.functions.Convert:cast character e0)))))
> 
> This mean is exp is a simple application (no splices or keywords) with one argument,
> then apply the following transformation.  This is evaluated during the
> InlineCall phase of the compilation.
> 
> When it comes to charToIntegerValidateApply it first "validates" argument 0
> in the context of the "required type" character (which is a 32-bit "primitive"
> character type).  It then wraps the result in a call to the low-lever Convert:cast
> procedure.  Assuming the types are correct, this will be a no-op.
> Then that result is cast to an int.
> 
> If all goes well and the incoming value is a 32-bit unboxed character or a 16-bit unboxed char,
> no code actually needs to be generated - which is the reason
> for using the charToIntegerValidateApply transformer in the first place.  Otherwise,
> you either get a compile-time error of the appropriate run-time conversion.
> 
> You can use (exp:getType) to get the type of the expression.
> 
> There is also the compile-apply property:
> 
> (define (values #!rest (args :: <Object[]>))
>  validate-apply: "kawa.lib.compile_misc:valuesValidateApply"
>  compile-apply: "kawa.lib.compile_misc:valuesCompile"
>  (invoke-static <gnu.mapping.Values> 'make args))
> 
> This causes the valuesCompile method in class kawa.lib.compile_misc
> to be called at code-generation time.  This is more low-level,
> and most of the code-generation are actually written in Java to
> generate custom byte-code depending on the argument expressions
> and their types.
> 
> (If I wanted to get the type of a standalone expression, I'd
> look at the implementation of eval (see kawa/lang/Eval.java), and do the same,
> but stop before code-generation.  Specifically,you would probably want to do
> compilation.process(Compilation.WALKED). Then you'd do something like
> compilation.getModule().body.getType().
> 
> However, that doesn't give you the type on an expression *in a lexical context*.)
> -- 
> 	--Per Bothner
> per@bothner.com   http://per.bothner.com/

--
Jamison Hope
The PTR Group
www.theptrgroup.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-22 22:18       ` Jamison Hope
@ 2017-09-22 22:26         ` Per Bothner
  2017-09-23 14:31           ` Jamison Hope
  0 siblings, 1 reply; 10+ messages in thread
From: Per Bothner @ 2017-09-22 22:26 UTC (permalink / raw)
  To: kawa

On 09/22/2017 03:18 PM, Jamison Hope wrote:
> OK, so if I understand correctly, I can't use a macro for this, but what
> I can do instead is write a function that always gets inlined.  The
> function itself doesn't really have to do anything, because the real
> work will be done in the validate-apply handler that rewrites the
> procedure application to a new Expression.  And there, I can decide what
> kind of Expression to construct based upon the Type of the argument
> expression.

100% correct.
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-22 22:26         ` Per Bothner
@ 2017-09-23 14:31           ` Jamison Hope
  2017-09-24 21:52             ` Per Bothner
  0 siblings, 1 reply; 10+ messages in thread
From: Jamison Hope @ 2017-09-23 14:31 UTC (permalink / raw)
  To: Kawa mailing list

On Sep 22, 2017, at 6:26 PM, Per Bothner <per@bothner.com> wrote:
> 
> On 09/22/2017 03:18 PM, Jamison Hope wrote:
>> OK, so if I understand correctly, I can't use a macro for this, but what
>> I can do instead is write a function that always gets inlined.  The
>> function itself doesn't really have to do anything, because the real
>> work will be done in the validate-apply handler that rewrites the
>> procedure application to a new Expression.  And there, I can decide what
>> kind of Expression to construct based upon the Type of the argument
>> expression.
> 
> 100% correct.

I found isEofValidateApply, which is extremely similar in form to what I
want, so I started with this:

(import (kawa expressions))

(module-export ensure-boolean validateEnsureBoolean)

(define (ensure-boolean o)
  validate-apply: "test:validateEnsureBoolean"
  (if o #t #f))

(define-validate validateEnsureBoolean (exp required proc)
  ((exp:isSimple 1 1)
   (exp:visitArgs (get-visitor))
   (let* ((e0 (exp:getArg 0))
          (t0 (e0:getType)))
     (cond ((eq? t0 boolean) e0)
           (else exp)))))


But I get a java.lang.Error when I try to compile that:


(compiling test.scm to test)
Exception in thread "main" java.lang.Error: gnu.kawa.lispexpr.LangPrimType does not implement Externalizable
	at gnu.expr.LitTable.error(LitTable.java:122)
	at gnu.expr.LitTable.writeObject(LitTable.java:282)
	at gnu.expr.LitTable.emit(LitTable.java:85)
	at gnu.expr.Compilation.generateBytecode(Compilation.java:2015)
	at gnu.expr.Compilation.process(Compilation.java:1810)
	at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:310)
	at gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:292)
	at kawa.repl.compileFiles(repl.java:780)
	at kawa.repl.processArgs(repl.java:441)
	at kawa.repl.main(repl.java:820)


If I change the test to "(eq? t0 integer)" or "(eq? t0 byte)", then it
compiles without error, so it's something about boolean in particular.


--
Jamison Hope
The PTR Group
www.theptrgroup.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-23 14:31           ` Jamison Hope
@ 2017-09-24 21:52             ` Per Bothner
  2017-09-25 16:58               ` Jamison Hope
  0 siblings, 1 reply; 10+ messages in thread
From: Per Bothner @ 2017-09-24 21:52 UTC (permalink / raw)
  To: Jamison Hope, Kawa mailing list

On 09/23/2017 07:31 AM, Jamison Hope wrote:
> But I get a java.lang.Error when I try to compile that:
> 
> 
> (compiling test.scm to test)
> Exception in thread "main" java.lang.Error: gnu.kawa.lispexpr.LangPrimType does not implement Externalizable
> 	at gnu.expr.LitTable.error(LitTable.java:122)
> ...

The problem is the 'boolean' has language-specific semantics, so the
variable 'boolean' is bound to the field kawa.standard.Scheme.booleanType.
However, the *class* of boolean is a gnu.kawa.lispexpr.LangPrimType, because
of this mismatch, the Kawa compiler doesn't find it when it needs to compile
boolean as a literal.

One could "fix" LangPrimType to implement Externalizable, but that would
create a new object, different from Scheme.booleanType.

A solution would be to create a new subclass SchemePrimType,
and do:
     public static final LangPrimType booleanType = SchemePrimType,booleanType;

Instead, I implemented a somewhat more general mechanism: If an object that
needs to be referenced as a literal implements HasOwningField, we use the
getOwningField of that interface to find the corresponding static field.

> If I change the test to "(eq? t0 integer)" or "(eq? t0 byte)", then it
> compiles without error, so it's something about boolean in particular.

Yes, integer is bound to LangPrimType.intType.  Since the code for compiling literals
looks for the class of the value, it can easily find the field.
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-24 21:52             ` Per Bothner
@ 2017-09-25 16:58               ` Jamison Hope
  2017-09-25 17:19                 ` Per Bothner
  0 siblings, 1 reply; 10+ messages in thread
From: Jamison Hope @ 2017-09-25 16:58 UTC (permalink / raw)
  To: Kawa mailing list

On Sep 24, 2017, at 5:52 PM, Per Bothner <per@bothner.com> wrote:
> 
> Instead, I implemented a somewhat more general mechanism: If an object that
> needs to be referenced as a literal implements HasOwningField, we use the
> getOwningField of that interface to find the corresponding static field.

That's working, thanks.

My validate-apply handler now looks like:

(define-validate validateEnsureBoolean (exp required proc)
  ((exp:isSimple 1 1)
   (let* ((e0 (visit-exp (exp:getArg 0)))
          (t0 (e0:getType)))
     (cond ((eq? t0 boolean) e0)
           ((eq? t0 int) (apply-exp = e0 0))
           ((eq? t0 void) (begin-exp e0 #t))
           (else (gnu.expr.ErrorExp
                  (format #f "unsupported expression type: ~a" t0)
                  (get-compilation)))))))


That looks very similar to my original hypothetical macro, so I'm
content.


Sorry for hijacking your thread, Sonny!

--
Jamison Hope
The PTR Group
www.theptrgroup.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: no class-of ?
  2017-09-25 16:58               ` Jamison Hope
@ 2017-09-25 17:19                 ` Per Bothner
  0 siblings, 0 replies; 10+ messages in thread
From: Per Bothner @ 2017-09-25 17:19 UTC (permalink / raw)
  To: kawa

On 09/25/2017 09:58 AM, Jamison Hope wrote:
> My validate-apply handler now looks like:
> 
> (define-validate validateEnsureBoolean (exp required proc)
>    ((exp:isSimple 1 1)
>     (let* ((e0 (visit-exp (exp:getArg 0)))
>            (t0 (e0:getType)))
>       (cond ((eq? t0 boolean) e0)
>             ((eq? t0 int) (apply-exp = e0 0))
>             ((eq? t0 void) (begin-exp e0 #t))
>             (else (gnu.expr.ErrorExp
>                    (format #f "unsupported expression type: ~a" t0)
>                    (get-compilation)))))))

Of course using eq? to compare type objects is going to be very fragile.
You might consider using (for example):
   (> (invoke int 'isCompatibleWithValue t0) 0)
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-09-25 17:19 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-21 11:11 no class-of ? Sonny To
2017-09-21 15:24 ` Per Bothner
2017-09-22 18:29   ` Jamison Hope
2017-09-22 19:23     ` Per Bothner
2017-09-22 22:18       ` Jamison Hope
2017-09-22 22:26         ` Per Bothner
2017-09-23 14:31           ` Jamison Hope
2017-09-24 21:52             ` Per Bothner
2017-09-25 16:58               ` Jamison Hope
2017-09-25 17:19                 ` Per Bothner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).