Hi,
My assumption was wrong… The following code is just a macro that generate 100000 functions and it compiles fine. At least you can have 100000 functions so it should be ok!!! The problem was that I was calling the |max| function. In the javascript backend this function only takes two args. In the scheme world it is an n-ary function.
Sorry for pointing out the wrong thing.
(declare (standard-bindings) (extended-bindings) (fixnum) (not safe))
(define-macro (generate-dummy-function-defs)
; reverse is not available (in target js) (define (myreverse l) (define (iter a b) (if (null? a) b (iter (cdr a) (cons (car a) b)))) (iter l (list)))
(define (iota n) (myreverse (riota n)))
(define (riota n) (if (= n 0) (cons 0 '()) (cons n (riota (- n 1)))))
`(begin ,@(map (lambda (i) `(define (,(string->symbol (string-append “fct” (number->string i)))) ,i)) (iota 100000))))
(generate-dummy-function-defs)
François
On Jan 24, 2014, at 10:52 AM, Francois Magnan magnan@categoricaldesign.com wrote:
Hi Marc,
It seems I stumbled on a problem with the javascript backend. When I compile my program I get an error message from gsc:
*** ERROR IN c#univ-dump-procs -- Wrong number of arguments passed to procedure (#<procedure #2> '#(#(target js #<procedure #3> #<procedure #4> #<procedure #5 c#target.dump> 5 #<procedure #6 c#target.prim-info> #<procedure #7 ... '#<procedure #8> '(("Gambit_" "stack") "[" (("Gambit_" "sp") (-2)) "]") '(("Gambit_" "stack") "[" (("Gambit_" "sp") (-1)) "]") '(("Gambit_" "stack") "[" (("Gambit_" "sp") (-4)) "]") ‘("Gambit_" ("r" 1)))
If I comment out some function definitions in my code I don’t get the error. It looks to me like there is a limit to the number of procedures that can be handled in a given file. It seems to be related to the maximum number of arguments a function can take.
Is there a way to split the code into multiple files?
Thank you, Francois Magnan
On 2013-11-23, at 09:54, Marc Feeley feeley@iro.umontreal.ca wrote:
On Nov 22, 2013, at 4:52 PM, Mikael mikael.rcv@gmail.com wrote:
(For general interest)
2013/11/22 Marc Feeley feeley@iro.umontreal.ca
On Nov 22, 2013, at 1:40 AM, Mikael mikael.rcv@gmail.com wrote:
Francois,
Two Q:s:
First, when you got a very basic sample app like a DOM-based hangman going, feel free to share code
Second, how is the type mapping - fixnums, flonums, bignums all wrapped to JS double, Scheme string and vector to JS string and vector?
(1) The data representation is customizable with two options for each type. There is a "natural" mapping (Scheme number -> JS number, Scheme vector -> JS array, etc) and one which uses classes.
(2) Note that the natural mapping may violate some of the Scheme semantics. For example, JS numbers don't carry the concept of exactness, and JS strings are immutable whereas Scheme strings are mutable. On the other hand the natural mapping may be useful in cases where some details of the Scheme semantics are not important (the generated JS code is easier to read/understand, the generated JS code can be more easily interfaced with existing JS libraries, etc). A mapping which respects the Scheme semantics is:
- Fixnums are mapped to JS numbers
- Booleans are mapped to JS booleans
- Symbols are mapped to JS strings
- Vectors are mapped to JS arrays
- Procedures are mapped to JS functions
- Strings, characters, flonums (and other numbers), and pairs are implemented with JS classes
Wait, first(1) you suggest there's a customizable option, and then second(2) you outline a holistic approach for Scheme-JS type mapping.
How is it? And if anything is configurable, where's the switch?
The source code of the universal backend was written to support both data representations, selectable for each type. So it is "customizable" in the sense that you simply have to change a single definition in _t-univ.scm to select the representation for each Scheme type (see the top of the file, e.g. (define (univ-flonum-representation ctx) 'class) ). It would be possible to expose these settings to the user, although it is not clear what is the best way to do that. Perhaps that could be part of the target's name, e.g.
gsc -target js file.scm gsc -target js-foo file.scm gsc -target js-bar file.scm
where foo and bar would indicate a particular choice of data representations that make some compromises (e.g. incomplete support of the Gambit specific features, lesser performance for some of the Gambit specific features, etc).
Unfortunately, this mapping makes it expensive to implement some Gambit specific operations, such as ##subtype, ##subtype-set! and
Didn't even hear about ##subtype* til now - Any use of JS turns out to be for some special purpose anyhow, so that there's some real corner case of Scheme execution in this environment that has a low performance is really completely cool.
The problem is that ##subtype, etc are used in the implementation of the Gambit runtime library. For example, ##subtype is used in the implementation of the procedure equal?-hash and some type predicates. So even if ##subtype is not used directly by users, some user callable procedures in the Gambit runtime library do use ##subtype.
##vector-ref.
Wait, why, can't this just be ordinarily expanded to JS' variable[index]?
Because ##vector-ref is used to access slots of many Gambit objects, not just vectors. For example the slot at index 0 of a symbol is the symbol's name, and the slot at index 0 of a structure is the type descriptor:
(##vector-ref 'foo 0)
"foo"
(##vector-ref (current-input-port) 0)
#<type #4 device-port>
If a Scheme datatype is represented using a JS class (for example a Scheme symbol is represented with a JS class with a "name" property), then (##vector-ref sym 0) if it is translated to sym[0] will not retrieve the name of the symbol. It would be possible to avoid this problem by using JS arrays to represent all memory allocated Gambit objects, but this would not be a natural translation (harder to understand the generated code, harder to write external JS code accessing the data representation, etc). Another approach would be to put some type dispatch logic in ##vector-ref to do the right thing with symbols, structures, etc, but this would slow down ##vector-ref.
Of course another approach would be to refactor the Gambit runtime system to replace such "unclean" uses of ##vector-ref by calls to type specific primitives. It is not clear how much work this would be (primitives have to be added to the compiler and the runtime system has to be refactored).
So it may be necessary to implement non immediate data (vectors, structures, etc) uniformly with classes when using the standard Gambit runtime system.
I haven't explored this aspect much, but it may be that supporting all the Gambit primitives isn't practical.
(same note as above re special purpose here)
A solution may be to have two modes (Standard Scheme and Gambit Scheme) so the user can select the best mode for his needs.
What would the difference be approx here?
Hard to say. The Gambit runtime system has to be examined carefully to see what would break for a particular choice of representation. For example, in a mode where number exactness is not supported (allowing all Scheme numbers to be represented with the JS "number" type, except for complex numbers), there will be a major impact on the numerical functions in lib/_num.scm . Some (how many?) will have to be modified to be consistent with the fact that there is no exactness. Should the lack of exactness be handled the same as treating all numbers as inexact numbers? etc.
Marc
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list