Personal tools

Yhc/Javascript

From HaskellWiki

< Yhc(Difference between revisions)
Jump to: navigation, search
(Building XHTML 2)
(Updated another couple of links)
 
(22 intermediate revisions by 5 users not shown)
Line 1: Line 1:
'''This page is work in progress. If you see a section that is empty revisit the page later: it will appear. Or let the [mailto:golubovsky@gmail.com developer] know what you would be interested to see on this page.'''
+
__NOTOC__
  +
===YCR2JS, a Converter of Yhc Core to Javascript===
   
==Brief Overview==
+
'''Note:''' There is also a [[Haskell in web browser|general tutorial for using Haskell in a web browser]]
An experimental sub-project, '''Yhc Core to Javascript Converter (ycr2js)''', is aimed to create a tool that generates Javascript out of a binary Yhc core file.
+
with YCR2JS.
   
The project was started as an experimental patch to [[Implementations#nhc98|nhc98]] in attempt to convert its internal PosLambda constructs into Javascript expressions. After some initial success, the project was switched to use the [[Yhc/API/Core|Yhc Core]] as the source for transformation. Recently, with a great amount of help from the [[Yhc]] Team, the project has been integrated into the main Yhc source tree and is moving towards closer integration with the compiler.
+
====Table of Contents====
 
Ability to convert an arbitrary Haskell source into Javascript makes it possible to execute Haskell programs in a Web browser. This, in turn, allows for development of both client and server sides of an Internet application entirely in Haskell.
 
 
Server side solutions in Haskell have been around for a while, such as [http://happs.org/HAppS/README.html HAppS -- Haskell Application Server], [http://www.cs.chalmers.se/~d00nibro/hsp/ Haskell Server Pages], and others. For the client side, [http://csmisc14.cs.chalmers.se/~bjornson/soc/ HSPClientSide] has been recently introduced, which is a close analog to '''ycr2js'''. HSPClientSide provides a domain-specific language to define the client side Web page structure (static HTML and Javascript). On the contrary, '''ycr2js''' helps convert any compilable Haskell source into Javascript.
 
 
==Principles of Operation==
 
The Yhc compiler generally produces a binary [[Yhc/RTS/hbc|bytecode]] file (usually named with ''.hbc'' extension) for each Haskell module compiled. These bytecode files are to be interpreted by [[Yhc/Tutorial#yhi|yhi]], a command-line bytecode interpreter.
 
 
The compiler is also capable of producing a binary [[Yhc/API/Core|core]] file (usually named with ''.ycr'' extension), and also its human-readable representation for each Haskell module compiled. The internal structure of core is based on significantly simplified nhc98's PosLambda constructs (Yhc is derived from nhc98 code). Core consists of definitions for compiled Haskell functions and data objects.
 
 
The feature of core linking was added recently to Yhc. This allows for merging core files from several modules together, removing functions that are not used (similar to static linking performed by a traditional Unix or Windows executable linker). The resulting file (usually named with ''.yca'' extension) has the same format as per-module core files.
 
 
Binary core files may be read back into computer memory using the [http://www.cs.york.ac.uk/fp/yhc/snapshot/docs/Yhc-Core.html Yhc Core API] functions.
 
 
The '''ycr2js''' program reads the binary core file specified (.yca or .ycr), and performs conversion of Haskell functions compiled into Core to their Javascript representation storing the generated Javascript code in a file. Resulting Javascript may be embedded on a (X)HTML page to be loaded into a Web browser.
 
 
==Users Guide==
 
 
<b>Note:</b> '''ycr2js''' is currently a standalone program distributed within the Yhc source tree. The usage guidelines below are relevant only for the standalone version. If '''ycr2js''' gets integrated in Yhc tighter than now, some or all of the following statements may be no longer applicable ansd will be updated accordingly.
 
 
===Downloading===
 
The '''ycr2js''' program along with additional tools is distributed within the Yhc source tree. Download and install Yhc as recommended [[Yhc#Installing_Yhc|here]] and [[Yhc/Building|here]]. Include the <code>core=1</code> options on the <code>scons</code> command line when building Yhc to generate Core for all Haskell library modules. The <code>yhc</code> and <code>ghc</code> executables should be on the PATH after the installation is coplete.
 
 
===Building and Installation on Unix===
 
Change from the toplevel directory of the Yhc source tree to the <code>src/translator/js</code> directory. Execute commands:
 
 
<code>
 
make all<br>
 
make install<br>
 
make test
 
</code>
 
 
All three commands should finish without error.
 
 
===Building and Installation on Windows===
 
 
This currently does not work, but will do once the Scons build system that Yhc uses has been integrated.
 
 
===What Is Installed===
 
The <code>Makefile</code> in the '''ycr2js''' directory instructs <code>make</code> to place all necessary files relatively to the <code>yhc</code> executable location. After the installation of '''ycr2js''', the directory structure will be as follows (assuming that ''prefix'' is the base path of the Yhc installation):
 
   
  +
# [[Yhc/Javascript/Brief_overview|'''Brief Overview''']]
  +
# [[Yhc/Javascript/Users_guide|'''Users Guide''']]
  +
# [[Yhc/Javascript/Programmers_guide|'''Programmers Guide''']]
  +
# [[Yhc/Javascript/Inner_workings|'''Inner Workings''']]
  +
# '''Examples and Demos'''
  +
----
 
{|
 
{|
 
|-
 
|-
|colspan="4"|''prefix''/bin
+
!Demo name:
  +
|'''"Does it leak?"'''
  +
|-
  +
|- valign="top"
  +
!Description:
  +
|This is an early preview of the features provided by the prototype of Haskell Web Toolkit (HsWTK), a thin layer on top of DOM which provides basic HTML layout capabilities and simulates cooperative pseudo-threads. HTML widgets displayed are self-explanatory. This demo program is also a memory leak test: please load it into various browsers and notice if browser executable size increases as certain user actions are performed. In fact, there should be no serious leaks, periodic browser size increases were noticed in Microsoft Internet Explorer v6, but at certain moments size decreased due to proper garbage collection. Browser size may even get smaller if the demo program page is unloaded. Mozilla Firefox did not show any memory leaks.
 
|- valign="top"
 
|- valign="top"
|width="2%"|&nbsp;||colspan="2"|ycr2js||Core to Javascript Converter
+
!Features:
  +
|Prototypic code of Haskell Web Toolkit:
  +
* Functions and combinators to describe appearance of a web form
  +
* Support for cooperative threads, events handling, message passing between threads
  +
* Widgets demonstrate interaction between HTML form elements
  +
* Programmable timer: while waiting, browser does not lock up
  +
<small>
  +
Some of these demo widgets are based on demo programs seen in [http://www.cse.chalmers.se/~hallgren/Thesis/main.html Fudgets Thesis]
  +
</small>
 
|- valign="top"
 
|- valign="top"
|&nbsp;||colspan="2"|pgbuild||XHTML Page Building Utility
+
!Tested with:
  +
|Firefox 1.5/Linux 32bit, Firefox 2.0/Linux 64bit, Opera 9/Windows 2000, MSIE 6.0/Windows XP: no noticeable memory leaks detected. MSIE does not display icons in the select element's dropdown menu.<br>
  +
<small><sup>feel free to add your own combination of browser/os where you got this demo working, fully or partially, note whether noticeable memory leaks were observed in response to users' actions.</sup></small>
 
|- valign="top"
 
|- valign="top"
|colspan="4"|''prefix''/lib
+
!Demo URL:
  +
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/HsWTKDemo.html
 
|- valign="top"
 
|- valign="top"
|&nbsp;||colspan="2"|haskell
+
!Stylesheet:
  +
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/HsWTK.css
 
|- valign="top"
 
|- valign="top"
|&nbsp;||width="2%"|&nbsp;||width="20%"|StdOverlay.hs||Standard Javascript Core Overlay
+
!Haskell Source:
  +
|http://www.cs.york.ac.uk/fp/darcs//yhc/web/jsdemos/HsWTKDemo.hs<br>
  +
|}
  +
----
  +
{|
  +
|-
  +
!Demo name:
  +
|'''"Echo"'''
  +
|- valign="top"
  +
!Description:
  +
|Type any text in the input field provided, and see it echoed right above after Enter is pressed. Just for fun, type any decimal number and see it converted to a Roman number, and vice versa. For more fun, a timer is provided: measure how fast your browser runs Haskell ;)
 
|- valign="top"
 
|- valign="top"
|&nbsp;||&nbsp;||UnsafeJS.hs||Contains <code>unsafeJS</code>, a pseudo-function to inline Javascript code in Haskell functions
+
!Features:
  +
|Lowest possible level of interaction with web browser:
  +
* Simple monadic framework
  +
* Wrapping Javascript functions to become Haskell functions
  +
* Calling Haskell functions from Javascript
  +
* Access to Javascript (including DOM) objects and properties
  +
* Handling of Javascript exceptions in Haskell
  +
* Events handling
  +
* Third party code of some "general" purpose works in web browser
 
|- valign="top"
 
|- valign="top"
|&nbsp;||colspan="3"|javascript
+
!Tested with:
  +
|Netscape 7/Linux, MSIE 6.0/Windows 2000, Konqueror 3.5.5/Linux, Opera/Windows, Firefox/ Mac OS X<br>
  +
<small><sup>feel free to add your own combination of browser/os where you got this demo working</sup></small>
 
|- valign="top"
 
|- valign="top"
|&nbsp;||&nbsp;||Runtime.js||Runtime Support Javascript Library, needs to be included with every XHTML page generated
+
!Demo URL:
  +
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Echo.html
 
|- valign="top"
 
|- valign="top"
|&nbsp;||colspan="3"|xhtml
+
!Haskell Source:
  +
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Echo.hs http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Roman.hs (C) Malcolm Wallace
  +
|}
  +
----
  +
{|
  +
|-
  +
!Demo name:
  +
|'''"Echo/Unicode"'''
 
|- valign="top"
 
|- valign="top"
|&nbsp;||&nbsp;||emptyx.html||An Empty XHTML Page template
+
!Description:
  +
|Around March 20, 2007, handling of Unicode character properties was added to the Yhc/Javascript runtime. This implementation is based on the Unicode Character Database available from the [http://www.unicode.org Unicode Consortium]. The database was compiled in Javascript and included in the output web page. This demo program is just recompilation of the same Echo source, but with the new runtime that supports Unicode. The Javascript Unicode Characters Database adds about 70k to the web page size.
  +
|- valign="top"
  +
!Features:
  +
|Same as in the above demo program. Replacement of functions like ''toUpper'', ''toLower'', ''isAlpha'' etc. to direct Javascript implementations affects the timing shown by the program: in some browsers there may be some speedup, in other browsers there may be a slowdown.
  +
|- valign="top"
  +
!Demo URL:
  +
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/EchoUnicode.html
 
|}
 
|}
+
----
The structure shown above represents a "bare" installation essential for '''ycr2js''' to function properly. Actual installation may include more files than these.
+
{|
 
The base location of Yhc installation will be further on referred as ''prefix'' unless otherwise stated.
 
 
===Compiling Haskell into Core===
 
In order to obtain a linked Core file for a Haskell source(s), the Yhc compiler should be run like this:
 
 
<code>
 
'''yhc''' -includes ''prefix''/lib/haskell \
 
[-includes other include directories] \
 
-linkcore Main.hs [other Haskell source files]
 
</code>
 
 
Other yhc options may be used as needed, but specifying the <code>''prefix''/lib/haskell</code> directory with the <code>-include</code> option is important. The <code>-linkcore</code> option instructs Yhc to link all core files generated together, along with library modules used. It is assumed that the user program's main module is named <code>Main</code>, and its entry point is <code>main</code>. Type signature of <code>Main.main</code> does not matter. The linked core will be output as the file <code>Main.yca</code>.
 
 
===Converting Core into Javascript===
 
In order to generate Javascript out of a linked core file (.yca), run the Core to Javascript converter:
 
 
<code>
 
'''ycr2js''' Main.yca Main.main >Main.js [2>Main.core]
 
</code>
 
 
The converter outputs generated Javascript into its standard output, and visual representation of the Core (after overlay and reachability check are applied, see details below). If redirection of standard error is omitted, visual representation of Core will not be saved.
 
 
The converter takes name of the linked Core file as its first command line parameter, and '''root names''' as the rest of parameters. The purpose of root names is to specify functions for which another functions they refer to (or, in other words, ''reachable'') will be kept. For example, a module may contain functions like this:
 
 
<haskell>
 
module Main where
 
 
import UnsafeJS
 
 
factorial :: Int -> Int
 
 
factorial 0 = 0
 
factorial 1 = 1
 
factorial n | n > 0 = n * (factorial (n - 1))
 
| n <= 0 = error "Factorial of a negative value"
 
 
anyStatus :: a -> a
 
 
anyStatus a = unsafeJS "window.status = exprEval(a).toString(); return a;"
 
 
str2 = 'a':'c':'d':"abyrvalg"
 
 
s5 :: String
 
s5 = 'g':[]
 
 
s6 :: String
 
s6 = 'd':""
 
 
s7 :: String
 
s7 = "ertyu"
 
 
main = anyStatus (["aaa","bbb",s7 ++ (head s7):(head s6):str2])
 
</haskell>
 
 
It can be easily seen that <code>Main.main</code> uses (of this module):
 
 
* anyStatus
 
* s7
 
* s6
 
* str2
 
 
and does not use:
 
 
* factorial
 
* s5
 
 
This means that the generated Javascript file will not contain <code>factorial</code> and <code>s5</code> just for the reason of size optimization.
 
 
It is possible that a script for a Web page contains several parts not linked symbolically, so don't forget what functions are "roots" and specify them all on the command line.
 
 
Another important thing to know about Javascript generation is '''Core Overlay'''. An overlay is a fake Haskell module containing declarations of functions to be replaced in the output Javascript file.
 
 
A good example of this is the <code>Prelude.error</code> function. It is defined in the [http://darcs.haskell.org/yhc/src/packages/yhc-base-1.0/Prelude.hs|Standard Prelude] as:
 
 
<haskell>
 
error :: String -> a
 
error s = primError s
 
 
primError :: String -> a
 
primError xs = trace (xs++"\n") (unsafePerformIO (exitWith (ExitFailure (negate 1))))
 
</haskell>
 
 
Not only is this definition irrelevant to Javascript execution in a Web browser (indeed, there is no ''traditional'' I/O), but it also pulls many other functions with it with the same low level of relevance. In the same time, the <code>Prelude.error</code> function is referred to from every <code>case</code> or <code>if</code> expression translated to Javascript.
 
 
The '''ycr2js''' program uses the overlay file, <code>''prefix''/lib/javascript/StdOverlay.hs</code>. Currently, only this overlay file may be used by '''ycr2js''' and its path is hardcoded into the program (although in the future, this limitation may be lifted). In an overlay file, names of functions (always qualified) to be replaced are encoded so for example a dot is replaced with prime-underscore sequence (the full set of decoding rules is defined in [http://darcs.haskell.org/yhc/src/libraries/core/Yhc/Core/Overlay.hs|Yhc.Core.Overlay] module in the function <code>decodeString</code>.
 
 
So, the Standard Overlay module defines <code>Prelude.error</code> to substitute one from the Prelude:
 
 
<haskell>
 
module StdOverlay where
 
 
import UnsafeJS
 
 
-- To substitute Prelude.error
 
 
global_Prelude'_error :: String -> a
 
 
global_Prelude'_error a = unsafeJS "alert(a); return undefined;"
 
</haskell>
 
 
which means that in the case of an error, an alert window will appear, and return of an <code>undefined</code> (in Javascript meaning) value will stop further script execution, most likely causing other error messages.
 
 
<small>
 
As an alternative, <code>Prelude.error</code> might throw an exception which unless caught would propagate to the top level and cause an error message to appear in Javascript Console, or in the browser's status line.
 
</small>
 
 
At this point, the generated Javascript is saved in the file <code>Main.js</code>.
 
 
===Building a XHTML Page===
 
In order to build a XHTML page ready to be loaded in a Web browser, another program that comes together with '''ycr2js''' is to be used:
 
 
<code>
 
'''pgbuild''' -t''prefix''/lib/xhtml/emptyx.html -o Main.html -T "Main" \
 
-e ''prefix''/lib/javascript/Runtime.js -e Main.js \
 
--onload="exprEval(Main_46main)"
 
</code>
 
 
The '''pgbuild''' program, given a XHTML page template, parses it (using the [[HXT|Haskell XML Toolbox]] package functionality, and embeds Javascript files (or script URLS) provided into the &lt;head&gt; section of the template. Additionally, page title and the <code>onload</code> attribute of page body may be changed.
 
 
The <code>-t</code> command line option is used to specify the path to the empty page template. A sample template (usable in many cases) comes with '''ycr2js''' and is located in <code>''prefix''/lib/xhtml/emptyx.html</code>. The <code>-o</code> option specifies where to place the output file. The <code>-e</code> option instructs that the following file name points to a script to be embedded, and the order of embedding is same as the order of appearance of file names on the command line. The <code>--onload</code> option results in the &lt;body onload="..."&gt; set to the value specified. The latter should be name of a function encoded as follows:
 
 
* all alphanumeric characters remain the same
 
* all other characters are replaced with an underscore followed by character's numeric code
 
 
so <code>Main.main</code> becomes <code>Main_46main</code>
 
 
<small>
 
would this be better to have '''pgbuild''' call ''fixStr'' itself and accept unmangled function names?
 
</small>
 
 
The XHTML Web page is written into the file <code>Main.html</code> and is ready to be loaded into a Web browser.
 
 
===Tools Summary===
 
 
===All Together: A Simple Makefile===
 
 
Here is an example of a simple Makefile containing rules sufficient to compile and build Web pages from Haskell sources. The <code>yhc</code> executable must be on the PATH.
 
 
Cutting and pasting this Makefile, don't forget about proper tabs usage.
 
 
<code>
 
#============ Begin Simple Makefile for Standalone ycr2js ============
 
 
YHC = yhc
 
YHCBASE = $$(dirname $$(dirname `which $(YHC)`))
 
YCR2JS = $(YHCBASE)/bin/ycr2js
 
PGBUILD = $(YHCBASE)/bin/pgbuild
 
XMLTMPL = $(YHCBASE)/lib/xhtml/emptyx.html
 
RUNTIME = $(YHCBASE)/lib/javascript/Runtime.js
 
HSJSLIB = $(YHCBASE)/lib/haskell
 
 
# Insert names of Web pages to build here. General naming rule:
 
# if the page is built out of a Haskell file Foo.hs which contains
 
# the main function, the Web page file name will be Foo.html
 
 
all: Foo.html
 
 
# If Foo.hs imports modules from any location other than current directory,
 
# add more -includes options to this rule.
 
 
%.yca: %.hs
 
$(YHC) -includes $(HSJSLIB) -linkcore $<
 
 
%.js: %.yca
 
$(YCR2JS) $< $*.main > $@ 2> $*.coreovr
 
 
# These two rules generate visual representation of Core.
 
# Include files with names ending with .yc[ra]txt in the list
 
# of `all' dependencies to build these files: .yca and .js files
 
# will be deleted by make in the very end.
 
 
%.ycatxt: %.yca
 
$(YHC) -viewcore $< > $@
 
 
%.ycrtxt: %.ycr
 
$(YHC) -viewcore $< > $@
 
 
# Don't forget that your "root" module Foo must contain the
 
# `main' function. Its type signature does not matter.
 
 
%.html: %.js
 
$(PGBUILD) -t $(XMLTMPL) -o $@ -T "$*" -e $(RUNTIME) -e $< \
 
--onload="exprEval($*_46main)"
 
 
#============= End Simple Makefile for Standalone ycr2js =============
 
</code>
 
==Programmers Guide==
 
 
===The <code>main</code> function===
 
 
===Calling Javascript from Haskell: <code>unsafeJS</code>===
 
 
===Calling Haskell from Javascript===
 
 
===Passing Primitive Values===
 
 
===Passing Strings===
 
 
===Passing Arrays===
 
 
===Passing Objects===
 
 
===Example: a Simple Monad===
 
 
==Inner Workings==
 
In this section, internal structure of Javascript objects and runtime support algorithms is reviewed.
 
 
===Javascript Objects===
 
 
The table below summarizes types of Javascript objects used in the '''ycr2js'''generated Javascript code.
 
 
{|border="1" bordercolor="gray"
 
|+<b>Javascript Object Types and Their Methods and Properties</b>
 
!Member/<br>Constructor!!Prop<br>Meth<br>Constr!!H<br>S<br>C<br>o<br>n<br>s!!H<br>S<br>E<br>O<br>L!!H<br>S<br>F<br>u<br>n!!H<br>S<br>D<br>l<br>y!!H<br>S<br>D<br>a<br>t<br>a!!colspan="4" width="90%"|Description/Arguments
 
 
|-
 
|-
!HSCons
+
!Demo name:
|style="text-align:center"|C||style="text-align:center"|*||&nbsp;||&nbsp;||&nbsp;||&nbsp;||valign="top"|Builds a list CONS cell||valign="top"|head:<br>head element||valign="top" colspan="2"|tail:<br>remainder of the list
+
|'''"Echo/DOM/CPS"'''
|-
+
|- valign="top"
!HSEOL
+
!Description:
|style="text-align:center"|C||&nbsp;||style="text-align:center"|*||&nbsp;||&nbsp;||&nbsp;||valign="top"|Final element of a list or an empty list||colspan="3"|&nbsp;
+
|Finally, the DOM framework has been implemented. IDL files provided by the [http://www.w3.org Web Consortium] were converted into set of Haskell modules using modified sources of [http://haskell.org/hdirect H/Direct], mainly the OMG IDL parser. The DOM framework uses [[Continuation]] passing style (CPS) rather than monadic style: this is believed to make adoption of [http://www.altocumulus.org/Fudgets/ Fudgets] easier as they use mainly CPS style in their internals. This demo web page looks similar to the previous Echo demo, and provides the same "functionality". This demo web page also uses unicode-enabled versions of character functions.
|-
+
|- valign="top"
!HSFun
+
!Features:
|style="text-align:center"|C||&nbsp;||&nbsp;||style="text-align:center"|*||&nbsp;||&nbsp;||valign="top"|Creates a function thunk with no arguments applied to||valign="top"|name:<br>function name to be used for debugging/exception tracing||valign="top"|arity:<br>arity of the function known by the compiler||valign="top"|body:<br>expression to apply to function's arguments and evaluate
+
|Utilization of the type-safe DOM Level1 interface:
|-
+
* Demonstration of the CPS style
!HSDly
+
* No unsafe direct access to Javascript objects needed: a library is now available
|style="text-align:center"|C||&nbsp;||&nbsp;||&nbsp;||style="text-align:center"|*||&nbsp;||valign="top"|A special object to wrap around a saturated function call||valign="top" colspan="3"|thunk:<br>saturated function call that is a HSFun object with number of arguments applied to (_a) equal to the function arity (_x); evaluation of this thunk will be delayed until it is applied to an argument which would have oversaturated the call in the absence of HSDly
+
|- valign="top"
|-
+
!Demo URL:
!HSData
+
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/EchoCPS.html
|style="text-align:center"|C||&nbsp;||&nbsp;||&nbsp;||&nbsp;||style="text-align:center"|*||valign="top"|Builds a data object other than a CONS cell or an Empty List||valign="top"|con:<br>constructor name (with non-alphanumeric characters replaced with underscored character codes)||valign="top" colspan="2"|arrs:<br>a Javascript Array containing contructor arguments
+
|- valign="top"
|-
+
!Haskell Source:
!_r
+
|http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/EchoCPS.hs<br> http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Roman.hs (C) Malcolm Wallace
|style="text-align:center"|P||style="text-align:center"|*||style="text-align:center"|*||style="text-align:center"|*||style="text-align:center"|*||style="text-align:center"|*||colspan="4" valign="top"|Boolean: true when a thunk may be evaluated.
 
* true in HSFun when the call is saturated (<code>_a.length == _x</code>)
 
* Always true in HSDly
 
* Always false in HSCons, HSEOL, HSData
 
|-
 
!_c
 
|style="text-align:center"|M||style="text-align:center"|*||style="text-align:center"|*||style="text-align:center"|*||style="text-align:center"|*||style="text-align:center"|*||colspan="4" valign="top"|Evaluate a thunk. If this method is said as "has no action", this means that it just returns <code>this</code> and does nothing else.
 
* No action in HSFun unless the call is saturated (<code>_a.length == _x</code>) in which case it applies the function body (_b) to the accumulated arguments array (_a) and returns whatever the body returns
 
* In HSDly, evaluates the delayed function call first <b>and then applies the oversaturating arguments to the result (_ap), and returns whatever results from this (a non-function value or unsaturated function call or saturated function call wrapped in another HSDly object)</b>
 
* No action in HSCons, HSEOL, HSData
 
|-
 
!_a
 
|style="text-align:center"|P||&nbsp;||&nbsp;||style="text-align:center"|*||style="text-align:center"|*||&nbsp;||colspan="4" valign="top"|Array:
 
* in HSFun, holds accumulated arguments
 
* in HSDly, holds oversaturating arguments
 
|-
 
!_ap
 
|style="text-align:center"|M||&nbsp;||&nbsp;||style="text-align:center"|*||style="text-align:center"|*||&nbsp;||colspan="2" valign="top"|Apply function call/delayed saturated call to argument(s)
 
* In HSFun, clones the HSFun object, and concatenates its argument to the accumulated arguments array (_a) of the copy. If the copy becomes a saturated call, sets it's _r property to true and returns the copy wrapped into HSDly, otherwise just returns the copy
 
* <b>In HSDly, clones the HSDly object and concatenates its argument to the oversaturating arguments array (_a) of the copy. No evaluation is done at this time; it will be performed by the _c method</b>
 
|colspan="2" valign="top"|targs:<br>Array containing the arguments to be applied to
 
|-
 
!_b
 
|style="text-align:center"|P||&nbsp;||&nbsp;||style="text-align:center"|*||&nbsp;||&nbsp;||colspan="4" valign="top"|Holds the expression to apply to function's arguments and evaluate: the third argument of the HSFun constructor is copied here
 
|-
 
!_x
 
|style="text-align:center"|P||&nbsp;||&nbsp;||style="text-align:center"|*||&nbsp;||&nbsp;||colspan="4" valign="top"|Holds the function arity: the second argument of the HSFun constructor is copied here
 
|-
 
!_n
 
|style="text-align:center"|P||&nbsp;||&nbsp;||style="text-align:center"|*||&nbsp;||&nbsp;||colspan="4" valign="top"|Holds the function name: the first argument of the HSFun constructor is copied here
 
|-
 
!_d
 
|style="text-align:center"|P||&nbsp;||&nbsp;||&nbsp;||style="text-align:center"|*||&nbsp;||colspan="4" valign="top"|Holds the saturated function call (HSFun object with <code>_a.length == _x</code>: the first argument of the HSDly constructor is copied here
 
|-
 
!_t
 
|style="text-align:center"|P||style="text-align:center"|*||style="text-align:center"|*||&nbsp;||&nbsp;||style="text-align:center"|*||colspan="4" valign="top"|Constructor name for a Data or a CONS/Empty list cell to be used for pattern matching
 
* In HSData, contains qualified name of the constructor that created the Data object with all non-alphanumeric character replaced with underscored character codes
 
* In HSCons, always contains "Prelude_46_58" (Prelude.:)
 
* In HSEOL, always contains "Prelude_46_91_93" (Prelude.[])
 
|-
 
!_f
 
|style="text-align:center"|P||style="text-align:center"|*||style="text-align:center"|*||&nbsp;||&nbsp;||style="text-align:center"|*||colspan="4" valign="top"|Constructor arguments (may be empty)
 
* In HSData, the second argument of the HSData constructor is copied here
 
* In HSCons, this is an array of two elements: copies of the first (head) and the second (tail) arguments of the HSCons constructor
 
* In HSEOL, always empty
 
|-
 
!toString
 
|style="text-align:center"|M||style="text-align:center"|*||&nbsp;||&nbsp;||&nbsp;||&nbsp;||colspan="4" valign="top"|Method of Object overridden by HSCons. Used for unmarshalling of Haskell lists (including Strings) into Javascript as Strings. The method evaluates all elements of the list (therefore it should be finite) and if the list contains characters, they are concatenated into a Javascript String, otherwise the _toArray method is called, and the toString method is called upon _toArray's result.
 
|-
 
!_toArray
 
|style="text-align:center"|M||style="text-align:center"|*||&nbsp;||&nbsp;||&nbsp;||&nbsp;||colspan="4" valign="top"|Method used for unmarshalling of Haskell lists (including Strings) into Javascript as Arrays. The method evaluates all elements of the list (therefore it should be finite) and concatenates them into a Javascript Array. Internal representation of Haskell type <code>Char</code> is its numeric value, so a Haskell <code>String</code> will be converted into a Javascript Array of <code>Number</code>'s.
 
 
|}
 
|}
  +
----
   
===Evaluation of Expressions===
+
--[[User:DimitryGolubovsky|DimitryGolubovsky]] November 17, 2007
The Javascript runtime support library provides a function <code>exprEval</code> which is used to evaluate all expressions starting with the toplevel expression (starting point).
 
 
In essence, this function looks like this:
 
 
<code>
 
function exprEval (e) {
 
for (var ex = e; ex != undefined && ex._r ; ex = ex._c())
 
;
 
return ex;
 
};
 
</code>
 
 
This is a loop that checks whether a given expression exists (not <code>undefined</code>) and can be evaluated <code>(_r == true)</code>. In this case, it calls the expression's _c method and analyzes its return. If the returned expression also may be evaluated, the function loops and evaluates it. This is repeated until an expression that no longer can be evaluated is returned (normal situation, e. g. a primitive value or a Data object), or an <code>undefined</code> value is returned (this is abnormal situation).
 
 
While evaluating an expression, <code>exprEval</code> may be recursively called to evaluate nested expressions.
 
 
===Special Notes===
 
====Oversaturation====
 
Oversaturation happens when a function thunk (HSFun object) is applied to more arguments than function arity (_x).
 
 
For example, this piece of Haskell code:
 
 
<hask>
 
let g = fst tup
 
x = g (5::Int) (6::Int)
 
</hask>
 
 
converts into the following Javascript (indentation manual):
 
 
<code>
 
var Bug_46Bug_46Prelude_46217_46g=
 
new HSFun("Bug.Bug.Prelude.217.g", <u>0</u>, function(){
 
var v285=new HSFun("v285", 0, function(){
 
return Prelude_46Prelude_46Num_46Prelude_46Integer;}
 
);
 
return (Prelude_46fst)._ap([(Bug_46tup)._ap([v285])]);
 
});
 
 
var Bug_46Bug_46Prelude_46218_46x=
 
new HSFun("Bug.Bug.Prelude.218.x", 0, function(){
 
return <u>(Bug_46Bug_46Prelude_46217_46g)._ap([5, 6])</u>;
 
});
 
</code>
 
 
As it can be clearly seen, <code>g</code> is defined with arity = 0 which is reasonable: its definition does not have any formal arguments. But when computing <code>x</code>, <code>g</code> is called with two arguments: 5 and 6.
 
 
To preserve laziness, the thunk of <code>g</code> should not be evaluated earlier than it is actually needed, i. e. when the value of <code>x</code> is needed. Calling the _ap method of <code>g</code> would have resulted in oversaturation and inevitable error in computations.
 
 
To work this around, logics of HSFun._ap method was changed, and special object type HSDly was introduced. HSFun._ap may accept any number of arguments in an array. Length of the array of arguments is compared with number of arguments needed to saturate the call. If the call becomes under- or completely saturated after the arguments have been applied to, no special action is taken: undersaturated call remains the same, saturated is wrapped in HSDly. If however oversaturation is about to happen, portion of arguments necessary to saturate the call is absorbed into the accumulated arguments array, and the rest of arguments are carried over to the HSDly._ap method.
 
 
Behavior of HSDly objects is as follows: the _ap method accepts as many arguments as provided, and accumulates them inside. The _c method evaluates the delayed thunk first, and then calls its _ap method with all the arguments accumulated up to the moment. In this case it is expected that the delayed thunk will evaluate into another function call (as can be seen in the example above). These actions may lead to either a value computed as result of application, or another function call, under-or completely or over-saturated. In the two latter cases, the result will be wrapped into another HSDly object with arguments remaining carried over.
 
 
==Examples and Demos==
 
*'''Echo'''<br>'''Description:''' Type any text in the input field provided, and see it echoed right above.<br>'''Tested with:''' Netscape 7/Linux<br>'''Demo URL''': http://darcs.haskell.org/yhc/web/jsdemos/Echo.html<br>'''Haskell Source:''' http://darcs.haskell.org/yhc/web/jsdemos/Echo.hs
 
 
 
--[[User:DimitryGolubovsky|DimitryGolubovsky]] 19:02, 6 November 2006 (UTC)
 

Latest revision as of 21:10, 16 December 2010

[edit] 1 YCR2JS, a Converter of Yhc Core to Javascript

Note: There is also a general tutorial for using Haskell in a web browser with YCR2JS.

[edit] 1.1 Table of Contents

  1. Brief Overview
  2. Users Guide
  3. Programmers Guide
  4. Inner Workings
  5. Examples and Demos

Demo name: "Does it leak?"
Description: This is an early preview of the features provided by the prototype of Haskell Web Toolkit (HsWTK), a thin layer on top of DOM which provides basic HTML layout capabilities and simulates cooperative pseudo-threads. HTML widgets displayed are self-explanatory. This demo program is also a memory leak test: please load it into various browsers and notice if browser executable size increases as certain user actions are performed. In fact, there should be no serious leaks, periodic browser size increases were noticed in Microsoft Internet Explorer v6, but at certain moments size decreased due to proper garbage collection. Browser size may even get smaller if the demo program page is unloaded. Mozilla Firefox did not show any memory leaks.
Features: Prototypic code of Haskell Web Toolkit:
  • Functions and combinators to describe appearance of a web form
  • Support for cooperative threads, events handling, message passing between threads
  • Widgets demonstrate interaction between HTML form elements
  • Programmable timer: while waiting, browser does not lock up

Some of these demo widgets are based on demo programs seen in Fudgets Thesis

Tested with: Firefox 1.5/Linux 32bit, Firefox 2.0/Linux 64bit, Opera 9/Windows 2000, MSIE 6.0/Windows XP: no noticeable memory leaks detected. MSIE does not display icons in the select element's dropdown menu.

feel free to add your own combination of browser/os where you got this demo working, fully or partially, note whether noticeable memory leaks were observed in response to users' actions.

Demo URL: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/HsWTKDemo.html
Stylesheet: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/HsWTK.css
Haskell Source: http://www.cs.york.ac.uk/fp/darcs//yhc/web/jsdemos/HsWTKDemo.hs

Demo name: "Echo"
Description: Type any text in the input field provided, and see it echoed right above after Enter is pressed. Just for fun, type any decimal number and see it converted to a Roman number, and vice versa. For more fun, a timer is provided: measure how fast your browser runs Haskell ;)
Features: Lowest possible level of interaction with web browser:
  • Simple monadic framework
  • Wrapping Javascript functions to become Haskell functions
  • Calling Haskell functions from Javascript
  • Access to Javascript (including DOM) objects and properties
  • Handling of Javascript exceptions in Haskell
  • Events handling
  • Third party code of some "general" purpose works in web browser
Tested with: Netscape 7/Linux, MSIE 6.0/Windows 2000, Konqueror 3.5.5/Linux, Opera/Windows, Firefox/ Mac OS X

feel free to add your own combination of browser/os where you got this demo working

Demo URL: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Echo.html
Haskell Source: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Echo.hs http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Roman.hs (C) Malcolm Wallace

Demo name: "Echo/Unicode"
Description: Around March 20, 2007, handling of Unicode character properties was added to the Yhc/Javascript runtime. This implementation is based on the Unicode Character Database available from the Unicode Consortium. The database was compiled in Javascript and included in the output web page. This demo program is just recompilation of the same Echo source, but with the new runtime that supports Unicode. The Javascript Unicode Characters Database adds about 70k to the web page size.
Features: Same as in the above demo program. Replacement of functions like toUpper, toLower, isAlpha etc. to direct Javascript implementations affects the timing shown by the program: in some browsers there may be some speedup, in other browsers there may be a slowdown.
Demo URL: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/EchoUnicode.html

Demo name: "Echo/DOM/CPS"
Description: Finally, the DOM framework has been implemented. IDL files provided by the Web Consortium were converted into set of Haskell modules using modified sources of H/Direct, mainly the OMG IDL parser. The DOM framework uses Continuation passing style (CPS) rather than monadic style: this is believed to make adoption of Fudgets easier as they use mainly CPS style in their internals. This demo web page looks similar to the previous Echo demo, and provides the same "functionality". This demo web page also uses unicode-enabled versions of character functions.
Features: Utilization of the type-safe DOM Level1 interface:
  • Demonstration of the CPS style
  • No unsafe direct access to Javascript objects needed: a library is now available
Demo URL: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/EchoCPS.html
Haskell Source: http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/EchoCPS.hs
http://www.cs.york.ac.uk/fp/darcs/yhc/web/jsdemos/Roman.hs (C) Malcolm Wallace

--DimitryGolubovsky November 17, 2007