Home

WaveScript Rev 3657 User Manual

image

Contents

1. This is an automatically generated table of primitives _ Int Int gt Int 3 4 ee ej _ Int Int gt Int and their type signatures Also see the libraries in 1ib for 7 Gan aO ne additional standard functions Int Int gt Int 116 Int16 Int16 gt Int16 cons Ca List a gt List a 116 Int16 Int16 gt Int16 car List a gt a 116 Int16 Int16 gt Int16 cdr List a gt List a 116 Int16 Int16 gt Int16 head List a gt a 116 Int16 Int16 gt Int16 tail r List a gt List a 164 Int64 Int64 gt Int64 append List a List a gt List a 164 Int64 Int64 gt Int64 List head 3 List a gt a 164 Int64 Int64 gt Int64 List tail List a gt List a 164 Int64 Int64 gt Int64 List ref List a Int gt a 164 Int64 Int64 gt Int64 List append List a List a gt List a Float Float gt Float List make Int a gt List a Float Float gt Float List length List a gt Int Float Float gt Float List reverse List a gt List a VA Float Float gt Float List toArray List a gt Array a ar Float Float gt Float List assoc List Ca b a gt List a b D Double Double gt Double List assoc_update List Ca b a b gt List a b D Double Double gt Double gint Int gt ta D
2. a Int gt a width Sigseg a gt Int start Sigseg a gt Int64 end Sigseg a gt Int64 timebase Sigseg a gt Timebase Array set Array a Int a gt O HashTable set_BANG HashTable key val key val gt HashTable rem_BANG HashTable key val key gt print a gt emit VQueue a a gt O break O gt a wserror String gt a inspect 1 Ta gt a GETENV String gt String FILE EXISTS String gt Bool SHELL String gt String SETCPU Int Stream t gt Stream t SETCPUDEEP Int Stream t gt Stream t map tr Ca gt b List a gt List b fold 1 Cacc b gt acc acc List b gt acc List map 1 Ca gt b List a gt List b List zip it List a List b gt List a b List fold Cacc b gt acc acc List b gt acc Array map Ca gt b Array a gt Array b Array fold Cacc b gt acc acc Array b gt acc Array andmap a gt Bool Array a gt Bool Array build Int Int gt a gt Array a 21
3. Of course you may want to import many functions from the same file or library WaveScript uses a very simple rule If a file has already been imported once repeated imports are suppressed This goes for source and object files Also if you try to import multiple files with the same basename e g bar o and bar so the behavior is currently unde fined 3 2 Foreign Sources A call to register a foreign source has the same form as for a foreign function foreign_source function name file list However in this case the function name is the name of the function being exported The call to foreign source will return a stream of incoming values It must be annotated with a type of the form Stream T where T is a type that supports marshaling from C code We call the function exported to C an entrypoint When called from C it will take a single argument convert it to the WaveScript representation and fire off a tuple as one element of the input stream The return behavior of this entrypoint is determined by the scheduling policy employed by that particular WaveScope backend For example it may follow the tuple through a depth first traversal of the stream graph returning only when there is no further processing Or the entrypoint may return immediately merely enqueu ing the tuple for later processing The entrypoint returns an integer error code which is zero if the WaveScope process is in a healthy state at the time t
4. 08 24 e Stream operators snoop on streams zip streams to gether sync them window rewindow and dewin dow them Interleave and deinterleave the elements of streams e Sigseg operators map functions over them lift some operations like fft to work on sigsegs e Basic math functions that are not included as primitive e Prints asserts and constant definitions e g 7 e Extended list and array operations not included as primitive e g List map2 e Shorthands for common procedures e g i2f for intToFloat e Curried versions of higher order operators 4 2 Fourier Transforms WaveScript uses fftw See prim_defs ss for a list of the dif ferent fft interfaces provided 4 3 Matrix Operations WaveScript uses the Gnu Scientific Library to support ma trix operations There are three files of interest within the wavescript lib directory The first gs1 ws declares pro totypes for accessing a subset of the low level GSL functions 17 directly You shouldn t need to use this file directly The second matrix_gsl ws which you should use provides a wrapper around GSL s matrix functionality that s more in the spirit of WaveScript Note that both of these files are generated by the C preprocessor from the corresponding pp files The third file of interest is matrix ws This is a native WaveScript library that implements the basic matrix oper ations described below using a simple array of arrays repre senta
5. 2 6 1 Dot syntax vas aus ed oe babe Ba ae OOP REE A eA RES SE KA SEG 11 2 6 2 5 Unary p rentheses s sss ici 444444445 04 bbe Ka badet de g sak EEE ESS 11 220 3 Stream Projectors 44 4 kes sok Ned eee Sew r SES SL EEE S 12 13 p ke GET b e CA SEE A SE ED EGGE EEE ESE KOS OY 13 EEE EE NG AE ee ee Pe eee eee eae ea ee eS 13 Ped DATE a abe eS OAD 4445458 de Sheds MS ea ay eee ee Seles 14 3 4 Foreign code in TinyOS ss aretas ee 14 3 5 Other b ckend s support s lt i son ask ske ak k ORRE GS a GE Je Gp GE ME GG MEL SG Gr ee deg 15 pH SEE SE SANE a S LAE ARS 15 EE AR A Nas a a AAA 15 3 8 Exclusive Pointers 16 A EOS 4 Standard Libraries AI NE ENN RRA LJ ON 4 2 Fourier Transforms se r oo a AA RR redene S T EEE EEG G Saa deal 4 3 Matrix Operations 4 3 1 Other numeric types 4 va k eee ss ma MG DASE KG ew ia 43 2 Matrix Interface s e e bres s e sal ae EE SOE JG MG DE a a t SOG SE Nate 5 WaveScript Evaluation Model 5 1 Execution Model A Primitive table 17 17 17 17 17 19 19 20 Chapter 1 Introduction WaveScript is a functional language for writing highly abstract programs that generate efficient dataflow graphs through a two stage evaluation model These graphs are executable in several backends Scheme ML C Java TinyOS that offer different tradeoffs in features perfor mance and compile times as well as parallel and distributed execution T
6. Double Double gt Double gt 1 Gta fa gt a D Double Double gt Double g Gta fa gt ta D Double Double gt Double gx 1 fa fa gt fa Complex Complex gt Complex g 1 fa fa gt fa i Complex Complex gt Complex g a a gt a Complex Complex gt Complex makeComplex Float Float gt Complex Complex Complex gt Complex int16Tolnt Int16 gt Int Ti Complex Complex gt Complex int16Tolnt64 Int16 gt Int64 realpart Complex gt Float inti6ToFloat Int16 gt Float imagpart Complex gt Float inti6ToDouble Inti6 gt Double sqrtl Int gt Int inti6ToComplex Int16 gt Complex sqrtF Float gt Float int64ToInt Int64 gt Int sqrtC Complex gt Complex int64Tolnt16 Int64 gt Int16 modulol Int Int gt Int int64ToFloat Int64 gt Float absI16 Int16 gt Int16 int64ToDouble Int64 gt Double absI64 Int64 gt Int64 int64ToComplex Int64 gt Complex absI 1 Int gt Int intToInti6 Int gt Int16 absF Float gt Float intToInt64 Int gt Int64 absD Double gt Double intToFloat sr Int gt Float absC Complex gt Float intToDouble Int gt Double logD Double gt Double intToComplex Int gt Complex exptI Int Int gt Int floatTolnt16 Float gt Int16 cos Float gt Float floatTolnt64 Float gt Int64 sin Float gt Float floatTolnt Float gt Int t
7. T2 T3 lists List T1 arrays Array T1 hashtables HashTable T1 T2 functions T1 T2 T3 gt T4 Note that parentheses must be used when nesting type con structors as in List List T 10 2007 03 09 In the future the user will be able to create their own type definitions and type constructors including tagged union or sum types 2 2 1 Reading data with readFile The one place where type annotations are currently man dated is when importing data from a file This is done with the primitive readFile Readfile is not a stream source but rather is driven by another stream reading a tuple from the file for every element on its input stream This makes it more general main readFile foo txt timer 10 0 Stream Int16 Float The above complete program reads space separated val ues from a text file one tuple per line In this case each tuple contains two values a 16 bit integer and a floating point value The readFile primitive may also be used to read data from a file in blocks Sigsegs which is generally more efficient All that is required is to specify a stream of Sigseg type as follows main readFile foo dat mode binary timer 10 0 Stream Sigseg Int16 repeat 3 Also note that the second argument to readFile is an option string This string is parsed at compile time dur ing meta program evaluation The string must contain a space separated list of alternating option na
8. and Sigsegs Valid expressions in WaveScript are written much as in C arithmetic 3 4 x 10 function calls f x y blocks e1 ez en But there are also many syntactic differences from C For example WaveScript doesn t have a sharp division between commands and expressions Conditionals use a different syntax and are valid in any expression position 3 if true then 1 else 2 4 Note that the arrow above means evaluates to but Wave Script does not currently have an interactive read eval print loop in which you can type such incomplete program frag ments Moreover blocks in WaveScript delimited by curly braces are just expressions 3 1 2 3 gt 6 This is similar to the begin end blocks found in other func tional languages or the comma operator sequencing con struct in C Only the value of the last expression within the block is returned the other statements expressions only bind variables or perform side effects Note that this different convention makes semi colon us age in WaveScript somewhat unintuitive Within blocks semi colons are only required as separators they are permit ted but not required after the last expression in the block Also since curly brace delimited blocks are merely expres 7 sions they sometimes must be followed with a semi colon as below 1 foo if b then I bar 0 else baz lt SEMICOLON REQUIRED done 2007 03 09 Be
9. clock gt Double Array null Array a realtime 1 Q gt Int64 nulltimebase Timebase Mutable ref a gt Ref a deref Ref a gt a timer List Annotation Float gt Stream prim window Stream a Int gt Stream Sigseg a ensBoxAudio Int gt Stream Sigseg Int16 ensBoxAudioF Int gt Stream Sigseg Float ensBoxAudioAll gt Stream Sigseg Int16 readFile List Annotation String String Stream a gt Stream b readFile List Annotation String Stream a String Int Int Int Int List Symbol gt Stream a readFile wsearly String Stream a String Int Int Int Int List Symbol gt Stream a fftC Array Complex gt Array Complex ifftC Array Complex gt Array Complex fftR2C Array Float gt Array Complex ifftC2R Array Complex gt Array Float memoized_fftR2C Array Float gt Array Complex unionList List Stream a gt Stream Int a _merge List Annotation Stream a Stream a gt Stream a feedbackloop Stream t Stream t gt Stream t gt Stream t gnuplot_array Array tta gt gnuplot_array2d gnuplot_process Array fa fb gt O Stream String Stream String gt Stream any spawnprocess String Stream String gt Stream String Array make Int a gt Array a Array makeUNSAFE Int gt Array a Array ref Array a
10. generate an efficient stand alone binary using one of our other backends One of these backends is the MLton backend invoked with wsmlton MLton is an aggressive whole program optimizing com piler for Standard ML Generating ML code from the Wave Script dataflow graph is straightforward because of the sim ilarities between the languages type systems This provides us with an easy to implement single threaded solution that exhibits surprisingly good performance while also en suring type and memory safe execution 1 3 2 The Low Level C Backend Invoked with wsc2 Moving forward this will serve as the primary Wave Script backend It has three purposes First it generates the most efficient code Second it serves as a platform for us to build custom garbage collectors the C backend sim ply uses Boost smart pointers and experiment with other aspects of the runtime Third it generates code with mini mal dependencies not requiring a runtime scheduler This last point was critical in adapting the backend to target Tiny OS described in the next section Currently 2008 08 15 wsc2 includes several garbage collection modes simple reference counting specialized de ferred reference counting boehm has some support for multithreaded execution some support for client server execution over a LAN using ssh and some support for client server execution over a network of sensor nodes run ning JavaME or TinyOS
11. is that it s interactive The query starts up paused and the user may step through and inspect the elements of the output stream Thus the user may pull on the stream rather than being pushed a torrent of output Variants of ws There are several other useful ways to invoke WaveScript with the Scheme backend Consider ws opt for higher performance The first thing to do to improve the performance of ws is make sure that you have the full version of Chez Scheme This version includes the incremental native code compiler If you are using the free Petite Chez Scheme interpreter your ws query files will be converted to interpreted Scheme code which runs considerably slower The executable chez should be in your path To go further you might consider running ws opt in place of ws First ws opt has debugging assertions dis abled Second ws opt is compiled in the highest Chez Scheme optimize level and also compiles your query in this higher optimize level However this optimize level is dan gerous in that it omits various checks necessary to main taining type safety Thus the process can crash if there s an error or memory can become corrupted just like C C Therefore debug your code using ws first Run ws debug occasionally for sanity checking Ws debug is too slow for the normal development cycle but it is important to occasionally compile your program with ws debug Mainly this is important for building confidence tha
12. refer to the CIDR 07 publication with the title The Case for a Signal Oriented Data Stream Management System for details Also check prim_defs ss for the specific names and type signatures of the Sigseg primitives 2 4 Namespaces WaveScript while not having a sophisticated module sys tem does include a simple system for managing namespaces namespace Foo KE sg VE 2455 var Foo x Foo y fun f I using Foo var x y 2 5 Patterns WaveScript allows pattern matching in addition to plain variable In any variable binding position it is valid to use a pattern rather than a variable name this includes the arguments to a function a local variable binding or the variable binding within an iterate construct Currently patterns are used to bind names to the interior parts of tuples In the future we will support list patterns and tagged union patterns Let s look at an example We saw how to bind variables in WaveScript z 1 2 This binds z to a tuple containing two elements This is actually a shorthand for the more verbose syntax let z 1 2 An unfortunate limitation of the parser is that let cannot be omitted if we a pattern is used in place of a simple identifier The following binds the individual components of the tuple by using a pattern in place of the variable z let x y 1 2 Similarly we may use patterns within a function s ar gument list Here s a functio
13. single mote connected to a serial interface we type the following joe computer wstiny split demo11g_tinyos ws joe computer make f Makefile tos2 telosb install joe computer query exe First we compile the program producing code for both platforms Second we install the progam onto the mote Third we execute the PC portion of the program which listens to the serial port unpacks the messages from the stream s2 and executes the rest of the program producing output to stdout as usual If we had compiled without split then the entire application would run on the mote Note the mote side communication is accomplished us ing the TinyOS interface AMSend which by default is wired to a SerialAMSenderC component If we want to execute on more than one mote we must instead wire this interface to the radio the AMSenderC component This is accomplished with joe computer wstiny split radio demolig Which is just shorthand for joe computer wstiny split with AMSenderC The resulting NessC code can be used to program sev eral motes Then the TinyOS included BaseStation ap plication can be used to enable a PC to receive these radio messages on its serial port This method described in the here Note that the semantics of this method is that the mes sages from every mote s s2 stream are combined to form the s2 stream seen on the PC Thus the s2 streams will most likely include the a node identifier so th
14. want to run parallelizable dataflow graphs where individual nodes are fast monomorphic first order C programs that don t require a heavyweight runtime In WaveScript your program essentially generates the special ized high performance stream processing program that is subsequently compiled and run How does this work WaveScript runs your program through an interpreter at compile time Your program re turns a stream value WaveScript must then make sure that it can convert that stream value back to code and re duce that code to fit the restrictions of the backend There are restrictions on the backend because we omit heavy weight language features to target tiny embedded devices e g no functions as values no closures Hence asymmet ric metaprogramming Your is therefore really two programs a meta program and an object program The meta program runs at compile time and generates the object program Other metapro gramming systems typically have heavyweight quotation mechanisms for explicitly constructing object code so you know exactly what object code you get out However these mechanisms are also very onerous and place a burden on the programmer WaveScript intentionally blurs the distinction between the stages uses the same language the same syntax se mantics and libraries for both stages and most of the time you don t need to think about it But sometimes you do In particular you have to be careful not to try t
15. Int gt a Array length Array a gt Int Array toList Array a gt List a m_invert Array Array fa gt Array Array fa internString String gt Symbol uninternString Symbol gt String HashTable make HashTable contains HashTable get Int gt HashTable key val HashTable key val key gt Bool HashTable key val key gt val HashTable set HashTable key val key val gt HashTable key val HashTable rem HashTable key val key gt HashTable key val iterate List Annotation in VQueue out gt VQueue out Stream in gt Stream out show a gt String gnuplot_array_stream gnuplot_sigseg_stream gnuplot_array_stream2d Stream Array a gt Stream Array a Stream Sigseg ft gt Stream Sigseg ft Stream Array ita b gt Stream Array fa b gnuplot sigseg stream2d Stream Sigseg fa b gt Stream Sigseg a b string append String String gt String String length String gt Int String explode String gt List Char String implode List Char gt String intToChar Int gt Char charToInt Char gt Int toArray Sigseg a gt Array a toSigseg Array a Int64 Timebase gt Sigseg a joinsegs Sigseg a Sigseg a gt Sigseg a subseg Sigseg a Int64 Int gt Sigseg a seg get Sigseg
16. The WaveScope process is thereafter broken any pending or future calls to entrypoints will return a non zero error code 3 3 Inline C Code The function for generating and including C code in the compiler s output is inline_C We want this bso that we can generate new parameterized C code by pasting strings together rather than including a static c or h file and instead of using some other mechanism such as the C pre processor to generate the C code The function is called as inline C c code init function Both of its ar guments are strings The first string contains raw C code top level declarations The second argument is either the null string or is the name of an initialization function to add to the list of initializers called before wsmain is called if present This method enables us to generate for exam ple an arbitrary number of C functions dependent on an arbitrary number of pieces of global state Accordingly we also generate initializer functions for the global state and register them to be called at startup time The return value of the inline C function is a bit odd It returns an empty stream a stream that never fires This stream may be of any type just as the empty list may serve as a list of any type This convention is an artifact of the WaveScript metaprogram evaluation The end result of metaprogram evaluation is a dataflow graph For the inline C code to be included in the final output of t
17. WaveScript Rev 3657 User Manual November 12 2008 Contents 1 Introduction 3 EEE GA GE RR Re Se be Ge SES GR RRS 3 1 2 Pragmatics Using WaveScript vr vr rv re r 4 1 2 1 ws The Interactive Scheme Backend kr knr knea 4 Le AE GE GSE SEE DREG AEE ferie Oh Gid Meh cel GO veve 5 1 3 1 The WaveScript MLton Backend 2 2 eee knea 5 1 3 2 The Low Level Backend saag sea kr ak SS RR ee BE eG AA ke een 5 1 33 The NesC TinyOS 2 0 Backend 2 2 0 0 0 0 rv krank 5 ENE SEE ee E a NE 6 1 4 1 The WaveScript CaML Backend 2 arr vr eee rea 6 1 42 The C XStream Backend rv vr rv rv rv nrk kerk 6 7 DO Streams va Saha base sea bades BE Se ee NET Sake ee ed Sa see EG 7 AER EEE 8 AR RO ee eee 8 LE a e dd dr E r a SSG 8 Ver PEN 8 AE AA EE EE EDEL a Ow 4 8 2 12 Numbers so om BARES Re e RR FEAT SSA GEN 8 DS Listes bk 4 a ae Re E LE eee NASSE oe oh be ka SEE 8 A NER 9 2 1 5 Extensible Records s ss e sa sem ag g dt RES GR GE EGG fk Be ew BB Od de feiet 9 2 1 6 Additional primitive functions erre rer ken 9 2 25 Type AMNOUAUIONS aar eda Es ee EE Res RE de KNR RG 10 EE EEE EE EE EEE ee oes 10 k AGE OA AN AEE EEE 11 EEE OE EE ENE EE EE EE EE ENTRET ORG 11 DAT Names paces e EE re re AA 11 2 0 Patterns cu aan a Re s Gid Ga due fete DAES SS oe a aw Ge NG var seer 11 FE aad gag AP AS ES nok Sk Sia ee a Nae kk eR Be A ANS 11
18. WaveScript compiler 3 conf2 Inject code into the implementation section of that configuration block 4 modl Inject code into the module block produced by the WaveScript compiler 5 mod2 Inject code into the implementation section of that module block 6 boot Inject code into the Boot booted event han dler This mechanism for inlining NesC code can be used for adding support for new timers or data sources In fact this is how existing functions like tos_timer and sensor_uint16 are implemented See internal wstiny ws inside the lib directory feature ws wsmlton wsc foreign yes yes yes foreign source never yes not yet inline C not yet yes not yet loads c yes yes yes loads h yes yes yes loads o yes not yet yes loads a yes not yet yes loads so yes no yes marshal scalars yes yes yes marshal arrays no yes not yet ptrToArray no yes not yet exclusivePtr yes not yet yes Figure 3 1 Feature matrix for foreign interface in different backends 3 5 Other backend s support The foreign interface works to varying degrees under each backend Below we discuss the current limitations in each backend The feature matrix in Figure 3 L gives an overview This has not been updated to address wsc2 Note that even though the Scheme backend is listed as supporting a and o files the semantics are slightly dif ferent than for the C and MLton backends The Schem
19. an Float gt Float floatToDouble Float gt Double acos Float gt Float floatToComplex Float gt Complex asin Float gt Float doubleToInt16 Double gt Int16 atan Float gt Float doubleToInt64 Double gt Int64 max Ca a gt a doubleToInt Double gt Int min Ca a gt a doubleToFloat Double gt Float Ca a gt Bool doubleToComplex Double gt Complex lt Ca a gt Bool complexToInt16 Complex gt Int16 gt Ca a gt Bool complexToInt64 Complex gt Int64 lt Ca a gt Bool complexToInt Complex gt Int gt it Ca a gt Bool complexToDouble Complex gt Double not Bool gt Bool complexToFloat Complex gt Float or Bool Bool gt Bool stringToInt String gt Int and Bool Bool gt Bool stringToFloat String gt Float foreign String List String gt any stringToDouble String gt Double foreign source String List String gt Stream any stringToComplex String gt Complex exclusivePtr Pointer name gt ExclusivePointer name roundF Float gt Float getPtr ExclusivePointer name gt Pointer name ta Int Int gt Int ptrToArray Pointer name Int gt Array a 20 ptrIsNull Pointer name gt Bool List build Int Int gt a gt List a ptrMakeNull O gt Pointer IS_SIM Bool inline_C String String gt Stream a nullseg Sigseg a
20. and a base station See the fol lowing section 1 3 3 The NesC TinyOS 2 0 Backend Invoked with wstiny 5 This backend inherits from wsc2 and modifies it to support TinyOS As of this writing 2008 02 22 the TinyOS backend is limitted in its supported language features See the end of this section for a list of limitations wstiny can be invoked in multiple ways First simply invoking wstiny on a WaveScript file in the same way as any other backend will compile the entire application to run on the mote joe computer wstiny demo11g_tinyos ws In the same way that one invokes query exe or query mlton exe when using another WaveScript back end one can run the wstiny program with query py joe computer query py This is a python script that invokes TOSSIM the TinyOS simulator The output of the program will be printed to the terminal including printed output and return values on the main stream again just like any other backend Of course the point of compiling for TinyOS is to run code on a mote This is slightly more involved After exe cuting wstiny we need to build the binary for the particular mote platform And then we invoke a listener on the serial port to see the output of the program joe computer make f Makefile tos2 telosb install joe computer MOTECOM serial dev ttyUSBO telosb joe computer export MOTECOM joe computer java PrintfClient wstiny has pollu
21. at the PC can demultiplex the stream Please see Section 3 4 for informa tion on integrating legacy TinyOS code with a WaveScript application Limitations e The above split methodology only works for one hop networks We must adapt it to use the CTP Collection Tree Protocol to work over larger networks e Code running on motes may not currently allocate memory dynamically e Only string constants static arrays numbers and tu ples are currently supported e Not all datatypes can be sent across a cut stream Currently tuples and numbers support marshaling in cluding nested tuples Arrays support marshaling but only if the array is not contained within a tuple Future plans We are in the process of removing the above limitations and adding support for new features e Dynamic allocation and garbage collection e Automatic and semi automatic partitioning of stream programs across PCs and motes 1 4 Deprecated Compiler Backends 1 4 1 The WaveScript CaML Backend This backend is no longer supported and will receive no new features But if you need to use it let me know 1 4 2 The C XStream Backend This backend is no longer supported and will receive no new features But if you need to use it let me know The C backend generates code that uses the XStream runtime scheduling engine It is invoked with the wsc command In practice as WaveScript undergoes de velopment the wsc compiler often lags be
22. ay has been allocated via malloc in C it s not possible to use it directly in WaveScript It lacks the necessary metadata and lives outside the space managed by the garbage collector However WaveScript does offer a way to unpack a pointer to C array into a WaveScript array Simple use the primitive ptrToArray But as with foreign functions be sure to include a type annotation See the table in Figure 3 1 for a list of backends that currently support ptrToArray 3 8 Exclusive Pointers Unfortunately ptrToArray is not always sufficient for our purposes When wrapping an external library for use in WaveScript it is desirable to use memory allocated outside WaveScript while maintaining a WaveScript like API For instance consider a Matrix library based on the Gnu Sci entific Library GSL as will described in the next chapter GSL matrices must be allocated outside of WaveScript Yet we wish to provide a wrapper to the GSL matrix operations that feels natural within WaveScript In particular the user should not need to manually deallocate the storage used for matrices For this purpose WaveScript supports the concept of an exclusive pointer Exclusive means that no code outside of WaveScript holds onto the pointer Thus when Wave Script is done with the pointer the garbage collector may invoke free to deallocate the referenced memory This is equivalent to calling free from C and will not for example suc
23. cessfully deallocate a pointer to a pointer Using exclusive pointers is easy There is one function exclusivePtr that converts a normal Pointer type ma chine address into a managed exclusive pointer By calling this the user guarantees that that copy of the pointer is the only in existence Converting to an exclusive pointer should be thought of as destroying the pointer it cannot be used afterwards To retrieve a normal pointer from the exclusive pointer use the getPtr function In the future getting an exclusive pointer will lock it and you ll have to release it to make it viable for garbage collection again Currently this mechanism is unimplemented so you must be careful that you use the Pointer value that you get back immediately and that there is a live copy of the exclusive pointer in existence to keep it from being free d before you finish with it 16 Chapter 4 Standard Libraries 4 1 stdlib ws Most of the basic stream operators window rewindow sync etc are contained within stdlib ws Thus most pro grams will start with include stdlib ws The file is contained within the 1ib subdirectory of the WaveScript root The top portion of the file contains type signatures for all the functions exported by the library Further down above each definition should be a brief explanation of its function Here is a high level overview of the functionality provided by stdlib ws as of 2007
24. cond they require that client code be fully aware of all the data inside the tuple and thus be fragile and difficult to refactor A solution to the first problem is to use named fields Tuples with named fields are called records similar to structs A solution to the second problem is to make those records extensible WaveScript implements the extensible record system documented in the paper Extensible Records with Scoped Labels by Dan Leijen 9 In WaveScript records are constructed in a manner sim ilar to tuples but with the labels on each data field Data fields can then be extracted using then common dot syn Record construction Extract the field A A 3 B true r A R I x But records can also be extended with new fields This uses a bar syntax as follows Cr A 3 Extend a record r A 3 A 3 The bar is optional here When updating records it is also possible to remove fields r A B 4 Remove field A add field B Removing a field and then replacing it is a common idiom and has a special syntactic sugar r B B 4 Remove field B add new B r B 4 Shorthand for the same Field labels are required to begin with capital letters in WaveScript This is to avoid conflict with another use of the dot syntax Extensible records are particularly useful in a streaming language like WaveScript In WaveScript the only commu nication betwee
25. crolling down to insert a close parenthesis myfunction iterate x in strm many lines 2 6 3 Stream Projectors WaveScript also includes a syntax for binding streams of tuples in a way that associates a projector function for each of the tuples fields For example S as a b someStream Subsequently S a or S a b a can be used to project a new stream where each tuple represents an ar rangement of the fields within each tuple in S If used in conjunction with the type annotation syntax note that the as clause must go first S as a b Stream Int Float someStream 12 Chapter 3 Foreign C C Interface The WaveScript compiler provides a facility for calling external foreign functions written in C or C The pri mary reasons for this are two fold 1 We wish to reuse existing libraries without modification e g Gnu Scientific Library FFTW etc 2 We wish to add new stream sources and sinks for network communication disk access and so on with out modifying the WaveScript compiler itself Also we frequently want to add support for new hardware data sources sensors There are three WaveScript primitives used to inter face with foreign code The foreign primitive regis ters a single C function with WaveScript Alternatively foreign source imports a stream of values from foreign code It does this by providing a C function that can be called to add a single tupl
26. e Bool int String char pointer to null terminated string Char char Array T T pointer to C style array of elements of type T where T must be a scalar type Pointer void Type for handling C pointers Only good for passing back to C Figure 3 2 Mapping between WaveScript and C types Conversions performed automatically 3 6 Converting WaveScript and C types An important feature of the foreign interface is that it de fines a set of mappings between WaveScript types and native C types The compiler then automatically converts where necessary the representation of arguments to foreign func tions This allows many C functions to be used without modification or wrappers Figure 3 2 shows the mapping between C types and WaveScript types 2007 08 24 Currently wsmlton does not automatically null terminate strings This needs to be fixed but in the meantime the user must null terminate them manually 2007 05 03 The system will very soon support conver sion of Complex and Int16 types types 3 7 Importing C allocated Arrays A WaveScript array is generally a bit more involved than a C style array Namely it includes a length field and po tentially other metadata In some backends wsc wsmlton it is easy to pass WaveScript arrays to C without copying them because the WS array contains a C style array within it and that pointer may be passed directly Going the other way is more difficult If an arr
27. e system can only load shared object files thus when passed 0 or a files it simply invokes a shell command to convert them to shared object files before loading them Including source files also has a slightly different meaning between the Scheme and the other backends Scheme will ignore header files it doesn t need them Then C source files c or cpp are compiled by invoking the system s C compiler On the other hand in the XStream backend C source files are simply included into the output C query file In the former case the source is compiled with no special link options or compiler flags and in the latter it is compiled under the same environment as the C query file itself Thus the C source code imported in this way must be fairly robust to the gcc configuration that it is called with If the imported code requires any customization of the build environment whatsoever it is recommended to com pile them yourself and import the object files into Wave Script rather than importing the source files 2007 05 03 Note Currently the foreign function inter face is only supported on Linux platforms It also has very preliminary support for Mac OS but has a long way to go 15 WaveScript C explanation Int int native ints have a system dependent length note that in the Scheme back end WaveScript Ints may have less precision than C ints Float float WaveScript floats are single precision Double doubl
28. e to the stream Thus we can call from WaveScript into C and from C into WaveScript The third primitive is inline C It allows WaveScript to gener ate arbitrary C code at compile time which is then linked into the final stream query We can of course call into the C code we generate from WaveScript or it can call into us 3 1 Foreign functions The basic foreign function primitive is called as follows foreign function name file list Like any other primitive function foreign can be used anywhere within a WaveScript program It returns a WaveScript function rep resenting the corresponding C function of the given name The only restriction is that any call to the foreign primi tive must have a type annotation The type annotation lets WaveScript type check the program and tells the Wave Script compiler how to convert if necessary WaveScript values into C values when the foreign function is called The second argument is a list of dependencies files that must be compiled linked into the query for the foreign func tion to be available For example the following would im port a function foo from foo c cfoo Int gt Int foreign foo foo c 13 Currently C code can be loaded from source files c cpp or object files o a so When loading from ob ject files it s necessary to also include a header h hpp For example c_bar foreign bar bar h bar a Int gt Int
29. el or within af block as follows fun f x y Zz x y sqrt z The function body following the argument list can be any expression Above it happens to be a statement block that returns the square root of z Unnamed or anonymous functions can occur anywhere that an expression might occur In the following we pass an anonymous plus three function as the first input to streammap Note that the body of the function is a single expression not a statement block and is not delimited by curly braces streammap fun x x 3 S 2 0 3 Constructing complete programs A complete program file contains function and variable dec larations As seen in Section 1 1 a special variable declara tion binds the name main to a stream main stream valued expression As a side note WaveScript can be called with a ret foo flag to return the stream foo instead of the stream main This is frequently useful for invoking testing entrypoints as well as the production entrypoint for the program Note also that only the returned stream is instantiated at runtime Other streams declared in the program will simply be ignored They become dead code 2 0 4 Tips for C Java Programmers As a quick cheat sheet refer to Figure 2 1 This addresses some minor syntactic differences between WS and C C that commonly trip people up One important piece of advice is to be careful with mu tation Don t u
30. for com patibility it also provides polymorphic operations directly under the Matrix namespace i e Matrix add There are definite advantages to the polymorphic interface For exam ple the Matrix map function can be used to apply a func tion f Float Complex to build a complex matrix from a float matrix The monomorphic versions can only map float matrices to float matrices and complex to complex Going further other GSL functionality The GSL libraries contained a wealth of functionality not currently exposed in WaveScript It is straightforward to ex tend gsl ws to export more of this functionality but there has not been the opportunity or need to do so at the mo ment You can see the GSL documentation here http www gnu org software gsl manual html_node If there s something you need bug Ryan to add it newton mit edu or take a look at gsl ws pp and matrix_gsl ws pp and try to add it yourself Chapter 5 WaveScript Evaluation Model WaveScript is a metaprogramming language For fur ther explanation I ll refer you to a quote from the Ma triz Reloaded that was brought to my attention by Yannis Smaragdakis NEO Programs hacking programs Why ORACLE They have their reasons The reason in WaveScript is that we want to write programs of a different character than we want to run We call this asymmetric metaprogramming We want to write abstract reusable polymorphic higher order pro grams but we
31. g how you should think of WaveScript 1 Everything is a value Streams and functions are just values or objects if your prefer The purpose of a WaveScript program is to return a Stream 2 But you need to understand multi stage evalu ation There are some restrictions on the code that executes inside iterates having to do with what fea tures are supported at runtime vs compile time This detracts from the simplicity of 1 because for exam ple function values may not be stored at run time We ll return to this issue in Chapter 5 1 2 Pragmatics Using WaveScript This section addresses pragmatic issues concerning invoking the system and running dataflow graphs If you are new to WaveScript it may help to skip to chapter 2 to get a sense for the language itself then come back to this section afterwards Installing See the README for install instructions The bottom line is that you will need Mzscheme and Petite Chez Scheme to run the WaveScript compiler and the Scheme backend Petite for Linux is included in the repository You will need Boost the Gnu Scientific Library GSL FFTW and their respective headers to run compiled C code Once the system is installed you should be able to ex ecute ws on any WaveScript source files ws files This will compile the query and execute it directly in the Scheme backend Other backends and variations on this one will be discussed in this section Develop Incrementall
32. get m i j M Int Int Float e set m i j val M Int Int Float e dims m M Float Float e row m i M Int gt Array Float e col m j M Int gt Array Float e toArray m M Array Float e fromArray arr diml Array Float Int gt M e fromArray2d arr diml Array Array Float e fromList2d arr dim1 List List Float M e submatrix m i j dim1 dim2 18 e build Int Int Int Int Float M e foreach Float M e foreachi Int Int Float M e rowmap Array Float ob M gt Array b e map Float Float M gt M e map2 Float Float Float M M gt M e map inplace Float Float M e map2 inplace Float Float Float M M The build foreach foreachi and map operations low the same conventions as the standard WaveScript container operators of the same names For example M Int Int Int Int Mata Floats cols f builds a matrix of the specified size by applying f at every i j index pair Additionally rowmap exposes each individual row as an array and the inplace map variants provide destructive updates A note on polymorphism The operations contained in Matrix Float are monomor phic They operate only on matrices of floats This is due to the fact that these are wrappers around non polymorphic native C routines While the pure WaveScript matrix imple mentation provides these monomorphic interfaces
33. he call completes Note that a zero return code does not guarantee that an error will not be encountered in the time between the call completion and the next invocation of the entrypoint Currently using multiple foreign sources is supported i e multiple entrypoints into WaveScript However if using foreign sources you cannot also use built in Wave Script timer sources When driving the system from for eign sources the entire WaveScript system becomes just a set of functions that can be called from C The system is dormant until one of these entrypoints is called Because the main thread of control belongs to the foreign C code there is another convention that must be followed The user must implement three functions that WaveScript uses to initialize start up the system and handle errors respectively void wsinit int argc char argv void wsmain int argc char argv void wserror const char Wsinit is called at startup before any WaveScript code runs e g before statel blocks are initialized and even before constants are allocated Wsmain is called when the WaveScript dataflow graph is finished initialing and is ready to receive data Wsmain should control all subse quent acquisition of data and feed data into WaveScript through the registered foreign_source functions Wserror is called when WaveScope reaches an error This function may choose to end the process or may return control to the WaveScope process
34. he compiler it must be included in this dataflow graph Thus inline C returns a stream that must in turn be included in the dataflow graph for the inline C code to be included You 14 can do this by using the merge primitive to combine it with any other Stream this will not affect that other stream as inline C never produces any tuples Alternatively you can return the output of inline C directly to the main stream as follows main inline C 3 4 Foreign code in TinyOS There are a few differences in how foreign code works in TinyOS The foreign source function is virtually the same The foreign function is similar but it should be noted that one can cheat a little by suppying an arbitrary string for the function name For example here is a foreign function that toggles an LED written using NesC s call syntax ledOToggle foreign call Leds ledOToggle O gt 0 Currently 2008 02 22 foreign only works for functions returning void Bug me to fix this The major difference lies in inline_C which is replaced by inline TOS TinyOS simply has more places that one might want to stick code thus more hooks are exposed inline TOS top confi conf2 modi mod2 boot All arguments are strings They inject code into different contexts as follows 1 top Inject code at top level not iside a configuration or module block 2 confl Inject code into the configuration block pro duced by the
35. he compiler has several command line entry points for the different backends 1 1 A taste of the language The academic publications on WaveScript will give you a top down account of its features reason for being and so on In this manual our goal is instead to introduce you to programming in WaveScript in a bottom up manner We ll start from Hello world and proceed from there Here s a simple but complete WaveScript program main timer 10 0 This creates a timer that fires at 10hz The return value of the timer function is a stream of empty tuples events carrying no information The return value of the whole program is by convention the stream named main The type of the above program is Stream where desig nates the empty tuple In our next program we will print Hello world forever main iterate x in timer 10 0 emit Hello world The iterate keyword provides a special syntax for access ing every element in a stream running arbitrary code using that element s value and producing a new stream as out put In the above example our iterate ignores the values in the timer stream x and produces one string value on the output stream on each invocation thus it prints Hello world at 10hz The type of the program is Stream String Note that we may produce two or more elements on the output stream during each invocation For example the following would produce two st
36. hind ws in terms of features and functionality Again develop incrementally refer to demos wavescope for programs that should work with wsc Refer to the XStream documentatior2 for information on how to configure the XStream engine number of threads scheduling policy etc 2007 03 09 Ideally the output from the XStream executed query would be the same as the ws s output Cur rently however there are some basic disparities in how ob jects are printed to text form Hopefully these are straight forward to work around and should go away Note that the C XStream backend does not have competitive performance with either the MLton backend or the newer ANSI C backend wsc2 Mt uses a C compiler not because it generates object oriented code but because the XStream runtime engine it links with has been engineered in C 212007 03 09 Currently nonexistent Chapter 2 Language Basics Please make liberal use of the demo files located at demos wavescope ws as a reference when learning Wave Script These demos cover most of the basic functionality in the language Wavescript is a functional language with many similari ties to ML or Haskell Functions are values The language is strongly typed and uses a type inference algorithm to in fer types from variable usages It provides the usual basic datatypes including various numeric types strings lists arrays hash tables as well as the more WaveScript specific Streams
37. mes and op tion values The following are the available options and their default values e mode one of text or binary default text e repeats a number specifying whether to replay the file s contents when the end of file is reached Set to a non negative integer to specify the number of repeats or to 1 to repeat indefinitely default 0 e rate the rate in tuples per second to play the back the data from the file For the emulator this refers to virtual time and is used only to maintain relative timing of different data streams Note that this is or thogonal to windowing whether data is windowed or not the rate will be interpreted in the same way de fault 1000 e offset The offset in bytes at which to start reading from the file default 0 e skipbytes The number of bytes to skip between read ing each tuple from the data file default 0 e window If the output stream is blocked into Sigsegs windows this parameter determines the size of each Sigseg default 1 2 2 2 Type Aliases Because types can grow large and complex it is often help ful to define aliases or shorthands similar to C C s typedefs type MyType List Int type MyType2 t Stream List t type MyType3 x List x type MyType4 x y List x y MyType 3 x x si MyType2 Int 2 3 Sigsegs Sigsegs are a flexible ADT for representing windows of sam ples on a stream Please
38. n different parts of the program is through streams Thus we typically need to pack data together to travel on a stream for example raw data plus metadata With extensible records it is possible to write an application as a series of modular components that take and produce records consuming some fields and adding others while remaining agnostic to the presence of unused fields Function foo takes a record that has at least X Y But might have other fields fun foo r I n f r X r Y r Z n add new results field This form of processing is very common in stream SQL dialects but here can be used in a more general purpose language with type inference 2 1 6 Additional primitive functions Appendix A contains a table of all currently supported WaveScript primitives together with their type signatures For more documentation on these primitives please refer to this file within your working copy src generic compiler_components prim_defs ss You can find the online documentation at http regiment us codedoc html generic compiler components prim defs ss html This file contains type signatures and minimal doc umentation for all built in wavescript primitives many of which are not covered in this manual Within the online documentation linked above you should look at which is defined in terms of regiment basic primitives wavescript primitives meta only primitives primitives and Please als
39. n that takes a 2 tuple as its second argument fun foo x y z 1 2 6 Syntactic Sugar Syntactic sugars are convenient shorthands that are imple mented by the parser and make programming in WaveScript more convenient at the risk of making reading code more difficult for the uninitiated 2 6 1 Dot syntax For convenience functions can be applied using an alterna tive dot syntax For example rather than taking the first element of a list with head 1s we can write ls head This generalizes to functions of more than one argument only the first argument is moved before the dot For exam ple List ref 1s i may be written as ls List ref i This is useful because many functions on data structures take the data structure itself as their first argument Thus it is concise to write the following ls tail tail head Note that this syntax requires that the name of the function not counting namespace modifiers begin with a lower case letter This is to avoid ambiguity with record field projec tion see Section 2 1 5 2 6 2 Unary parentheses The operator for procedure application is taken from Haskell and sometimes called the unary parenthesis In stead of f g x we write f g x This is useful if you have a large expression spanning many lines to which 11 You want to apply a function iterate x in strm 4 many lines We can apply a function myfunction without s
40. nded to include 8 bit integers other unsigned integers and complex doubles WaveScript includes generic numeric arithmetic operations that work for any numeric types but must be used on two numbers of the same type There are also type specific numeric operations that are not used frequently generic x 7 Int tdo Ta Float Sp RE fe 7 Complex r Int16 116 116 I16 116 7116 Int64 164 164 164 164 7164 Other numeric operations such as abs or sqrt follow the naming convention absI for integers absF for floats absC for complex and absI16 for 16 bit integers Eventu ally WaveScript will include a type class facility which will simplify the treatment of numeric operations 2 1 3 Lists Lists can be written as constants and support the usual primitive operations ls 1 2 3 1s2 head 1s 1s print List length 1s2 Prints 74 print ls Prints false The operator adds an element to the front of a list Also use head tail List reverse List append to oper ate on lists Other operations include but are not limited to the fol lowing List zip combines two equal length lists into a list of two tuples List map f 1s returns a new list generated by applying the function f to each element of the input list List filter pred 1ls returns only those elements of the list that satisfy pred List fold op init 1ls reduces a list by repeatedly applying op to
41. o examine the library files found in the 1ib sub directory These files for example stdlib ws and matrix ws include library routines written in Wave Script As a general design principle it is best to implement as much as possible in the language while keeping the set of built in primitives relatively small For various historical reasons there are several primitives included in the current primitive table that should not ulti mately be primitive These will eventually be removed and implemented instead as library routines Likewise there are certainly many additional primitives that one might like to see incorporated as the language matures 2 2 Type Annotations We have already seen several types in textual form within this manual Float Int String These are valid Wave Script types WaveScript also has compound types such as Sigseg Array Int Similar to Haskell or ML the user is permitted but not generally required to add explicit type annotations in the program For example we may annotate a function f with its type by writing the following f Type Type gt Type fun f x y 1 Indeed a type annotation may be attached to any ex pression with the following syntax expression Type Further type annotations may be added to variable dec larations with var Type expression In general compound types may be built from other types in several ways tuples T1
42. o store function values in data structures within object code in side iterates Recursive functions are also currently dis allowed in object code 19 5 1 Execution Model UNFINISHED After the metaprogram evaluates what is left is a dataflow graph of stream operators kernels Now you may ask what are the semantics of this dataflow graph s exe cution WaveScript implements an asynchronous dataflow model Streams are sequences discrete events with no implied synchronization Stream kernels are thus event handlers Further the order of evaluation of kernels within a data flow graph is entirely at the whim of the scheduler subject to loose fairness constraints Any kernel with input data available is ready and may execute at any time yet no ready kernel may execute an infinite number of times without all other ready kernels executing Therefore computations must be robust to the timing of the communication channels between kernels After all the program may be distributed with some channels going over slow wireless links and other channels intra node How do we accomplish this Well we rely on well engineered li braries to insulate programmers from as much of the pain of asynchronicity as possible In particular be careful when ever multiple streams are being merged If there is a one to one correspondence between stream elements use zip library functions if possible Appendix A Primitive table
43. pairs of elements for ex ample to sum the elements of a list List mapi f 1s isa variant of map that also passes the index of the element to the input function List foreach f 1s applies a function to each element for side effect only not building a new list List build len f builds a new list using a function on index to populate each position in the list Many of these operators map filter foreach mapi fold build etc are used consistently for different container types lists arrays matrices etc 2 1 4 Arrays Arrays unlike lists are mutable Use a hash symbol to build a constant array rather than a list for example 1 2 3 Use Array make to allocate new arrays The Array ref and Array set primitive access arrays elements but it s shorter to use the syntactic sugar arr i to access arrays and arrlil x to modify them Nested array refer ences work as expected as do the style shorthands e g arr i j 3 However to use these shorthands with an arbitrary non variable expression extra parentheses are required f x i Many array operations are analogous to the list opera tions map fold etc See the documentation for additional primitives below 2 1 5 Extensible Records Tuples are useful for packing together a small number of data items But from a software engineering perspective they have a number of limitations First they quickly grow confusing as the number of items increases Se
44. rators such as toArray row and column is that they provide no guarantee as to whether or not they return an alias to the existing storage in the ma trix or newly allocated storage We need to leave both these possibilities open because of the diversity of possible backends platforms and matrix implementations Thus the Arrays returned from these operations must be treated as immutable In addition to the above basic matrix functions the ma trix library namespace also includes common linear algebra matrix operations e add ml m2 M M gt M e sub m1 m2 M M gt M e mul elements ml m2 M M gt M e div elements ml m2 M M gt M e scale m coef M Float gt M e add_constant m1 const M Float gt M e mul m M M gt M gt M e invert m M gt M The above operations are purely functional That is they do not destroy their arguments they allocate new matrices to store the results of their computations Because matrices can be large this is not always desirable The matrix library includes destructive in place versions of all the above opera tions except mul and invert for example add inplace These mutate their first argument and return unit O rather than returning a new matrix Higher order matrix operations Below are additional higher order matrix operations those that take functions as arguments e create diml dim2 Int Int gt M e eq m1 m2 M M Bool e
45. ring elements for each input element on the timer stream main iterate x in timer 10 0 4 emit Hello world emit Hello again Actually timers are the only built in WaveScript stream sources All other built in stream procedures only transform existing streams Iterate also allows persistent mutable state to be kept be tween invocations This is introduced with the sub keyword state For example the following produces an infinite stream of integers counting up from zero main iterate x in timer 10 0 4 state cnt 0 emit cnt cnt cnt 1 Notice that the assignment operator for mutating mu table variables is different than the operator used for declaring new variables WaveScript also has etc for use in mutating variables It is also possible for mutable state to be declared outside the scope of the iterate but that introduces the possibility of referring to the state from the bodies of two different iterates which is not allowed As a final example we ll merge two streams operating at different frequencies si iterate x in timer 3 0 emit 0 s2 iterate x in timer 4 0 emit 1 main merge s1 s2 This will output a sequence of zeros and ones with four ones for every three zeroes The merge operator combines two streams of the same type interleaving their elements in real time Before we get into the nitty gritty I will leave you with two high level points regardin
46. se it when it s unnecessary And if you need to use it keep the scope of the variables in question as small as possible If for example you introduce mutable top level global variables it may have major deleterious effects First of all it opens up the possibility that you will refer to the state from multiple iterate bodies which will make the compiler yell at you More subtly it can dis able optimizations that act on iterates without persistent state for example replicating them in parallel 8 C C code WS Equivalent int x 3 x 3 OR x 3 Int x Int 3 x 4 x 4 if a b else c typedef char myty List lt Array lt int gt gt if a then b else c type myty Char List Array Int Figure 2 1 Some highlighted syntactic differences between WaveScript and C C Java 2 1 Datatypes This section goes over syntax and primitives for manipulat ing built in data structures 2 1 1 Tuples Tuples or product types are ordered sets of elements which can each be of different types 1 hello A tuple of type Int String Tuples are accessed by a pattern matching against them and binding variable names to their constituent components This process is described in section 2 5 2 1 2 Numbers WaveScript supports several different types of numbers Currently this set includes Int Int16 Uint16 Int64 Float Double Complex but it will be exte
47. t the compiler is behaving properly on your program If the compiler were a mature system not under active devel opment this would not be as important Specifically when you run ws debug 1 It turns on extra ASSERT statements in the code that check data structure invariants to help ensure proper operation 2 It dumps the whole program at several points in the compilation to files such as __elaboratedprog ss It can be helpful to look at these for debugging 3 It includes additional type checks of the entire program between passes regular ws type checks several times but ws debug does more This helps expose compiler bugs 4 Finally it does grammar checks on the output of each compiler pass Each pass includes a BNF grammar that describes its output ws debug mechanically checks to make sure every intermediate expression conforms to the appropriate grammar Again this helps to expose compiler bugs For very low compile times ws early If you are running many small programs stream queries then the latency of compilation may be more important to you than the throughput of the query once it is running In this case it is reasonable to use ws early 1 3 Premier Compiler Backends 1 3 1 The WaveScript MLton Backend The WaveScript Scheme backend ws provides a reference implementation suitable to prototyping and debugging ap plications The eventual target for most WaveScript pro grams is to
48. ted your working directory with sev eral files including Makefile tos2 PrintfClient java query py and others The PrintfClient program can listen to a particular device specified either through the MOTECOM environment variable or through a comm flag Please refer to the the TinyOS documentation for instructions on how to connect motes to your computer Executing across mote and PC Alas it is not very interesting to simply run code on a mote that is attached to a PC s serial port For a real sensor network application we need to run WS code on an entire sensor network and on the PC connected to the network seemlessly splitting the application across the two tiers Currently wstiny supports a method for manually split ting programs across tiers This is implemented using a simple naming convention A Node namespace contains all the streams that will live inside the network and ev erything outside of that namespace lives on the PC The following program illustrates this method but it may help to return to it after reading Section 2 and in particular Section which explains namespaces namespace Node SLE sa 52 S as main smap 1 Node s2 Only the 1 operation is executed on the PC The cut point that splits s2 between the mote and PC will cause the compiler to generate code on both sides that ac complishes the communication To compile this program and execute it across the PC and a
49. tion Except for a few operations implemented only in the GSL based version the libraries should be interchange able You should choose which to use based on the opera tions you need availability of GSL on the target platform and performance requirements 4 3 1 Other numeric types All of the below matrix operations are explained with the example of 32 bit floating point matrices These operators are contained in the namespace Matrix Float and can may be referred to with fully qualified names Matrix Float add or by first importing the namespace using Matrix Float followed by only the short name get Also included in the matrix library are analo gous routines in the Matrix Complex and Matrix Double namespaces 4 3 2 Matrix Interface Here are the functions contained within the namespace Matrix Float On the left is a typical function call with meaningful names for the arguments and on the right is the WaveScript type of the function For brevity M is used to abbreviate the type Matrix Float which in turn is a type alias for whatever the internal representation of a matrix is 1 Currently the invert available for Matrix Double operation is only This basic interface includes functions for creating a ze roed matrix accessing and mutating it and converting to and from one dimensional row major arrays or from two dimensional arrays and lists very important note about Array extraction ope
50. wary that with the current parser a semi colon error may appear as a strange parse error in the next or previous line 2 0 1 Streams WaveScript is for stream processing and it would be useless without Streams Streams in WaveScript are like any other values bound to variables passed and returned from func tions The primary means of operating on the data inside streams is the iterate syntactic construct S2 iterate x in Si i state counter 0 counter counter 1 emit counter x gt The iterate construct can be placed in any expression position It produces a new stream by applying the sup plied code to every element of its input stream The above example executes the body of the iterate every time data is received on the stream S1 it adds an increasing quantity to each element of S1 and the resulting stream is bound to the variable S2 In addition to iterate several library procedures such as stream_map and many primitives such as unionList operate on Stream values For example merge combines lAs a special case when a function body consists of curly braces it needn t be followed by a semi colon two streams of the same type their tuples interleaved in real time whereas unionList also combines streams of the same type but tags all output tuples with an integer index indicating from which of the input streams it originated 2 0 2 Defining functions Named functions can be defined at the top lev
51. y WaveScript is a research compiler It doesn t offer the same level of support that you expect from production quality compilers Sometimes the error messages might be diffi cult to interpret However the type checker messages have been improved immensely and do include code locations 04 08 2007 Therefore it helps to build your program bit by bit Com pile often to make sure that the pieces of your program parse and type check wsparse While entrypoints such as ws parse source files internally if you want the full error message for a parser error including line and column number run wsparse di rectly on the ws file It will either print the AST abstract syntax tree for the file or will give you an error message that does include line and character numbers 1 2 1 ws The Interactive Scheme Backend Running the command ws mysource ws will compile your source file and execute the resultant dataflow graph directly within Scheme without generating code for another platform The dataflow graph is converted to a Scheme pro gram which is compiled to native code and executed on the fly Compile time is low because we need not call a separate backend compiler However performance is not as good as the other backends we will discuss Further the Scheme backend does not support external real time data sources only queries running in virtual time using data stored in files One major advantage of the Scheme backend

Download Pdf Manuals

image

Related Search

Related Contents

2.4GHz Digital Wireless A/V/Data Transmitter and Receiver KIT  Samsung GT-S5300 Korisničko uputstvo  scanCONTROL Configuration Tools 4.1 - Micro    自転車用発電ランプ(MG-V48-H1型)  Betriebsanleitung SERIE Z60-000  Manual for the 23582 Bandstand Bears  Gigabyte GB-BXi5G3-760 (rev. 1.0)  

Copyright © All rights reserved.
Failed to retrieve file