Type-Specialized Staged Programming with Process Separation Yu David Liu, State University of New York at Binghamton Christian Skalka, University of Vermont.

Slides:



Advertisements
Similar presentations
Objects and Classes David Walker CS 320. Advanced Languages advanced programming features –ML data types, exceptions, modules, objects, concurrency,...
Advertisements

Intermediate Code Generation
Semantic Analysis Chapter 6. Two Flavors  Static (done during compile time) –C –Ada  Dynamic (done during run time) –LISP –Smalltalk  Optimization.
Current Techniques in Language-based Security David Walker COS 597B With slides stolen from: Steve Zdancewic University of Pennsylvania.
COS 461 Fall 1997 Routing COS 461 Fall 1997 Typical Structure.
Declarative sensor networks David Chu Computer Science Division EECS Department UC Berkeley DBLunch UC Berkeley 2 March 2007.
Pedigree Types Yu David Liu, Johns Hopkins University / SUNY Binghamton Scott F. Smith, Johns Hopkins University July 7, IWACO’08.
Rigorous Software Development CSCI-GA Instructor: Thomas Wies Spring 2012 Lecture 11.
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
Elementary Data Types Prof. Alamdeep Singh. Scalar Data Types Scalar data types represent a single object, i.e. only one value can be derived. In general,
Distributed Meta- Programming Rui Shi, Chiyan Chen and Hongwei Xi Boston University.
Chapter 5: Elementary Data Types Properties of types and objects –Data objects, variables and constants –Data types –Declarations –Type checking –Assignment.
Type Checking.
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 18.
Objects and Classes David Walker CS 320. Advanced Languages advanced programming features –ML data types, exceptions, modules, objects, concurrency,...
Introduction to Java Kiyeol Ryu Java Programming Language.
Vertically Integrated Analysis and Transformation for Embedded Software John Regehr University of Utah.
Tiny OS Optimistic Lightweight Interrupt Handler Simon Yau Alan Shieh CS252, CS262A, Fall The.
CS 104 Introduction to Computer Science and Graphics Problems
Slides prepared by Rose Williams, Binghamton University Chapter 5 Defining Classes II.
Chapter 9: Subprogram Control
Chapter 10 Implementing Subprograms. Copyright © 2007 Addison-Wesley. All rights reserved. 1–2 Semantics of Call and Return The subprogram call and return.
Cormac Flanagan University of California, Santa Cruz Hybrid Type Checking.
MAC Layer Protocols for Sensor Networks Leonardo Leiria Fernandes.
C++ fundamentals.
1/25 Pointer Logic Changki PSWLAB Pointer Logic Daniel Kroening and Ofer Strichman Decision Procedure.
C++ Functions. 2 Agenda What is a function? What is a function? Types of C++ functions: Types of C++ functions: Standard functions Standard functions.
Floating point variables of different lengths. Trade-off: accuracy vs. memory space Recall that the computer can combine adjacent bytes in the RAM memory.
1 Chapter 5: Names, Bindings and Scopes Lionel Williams Jr. and Victoria Yan CSci 210, Advanced Software Paradigms September 26, 2010.
Imperative Programming
IT253: Computer Organization Lecture 4: Instruction Set Architecture Tonga Institute of Higher Education.
Power Save Mechanisms for Multi-Hop Wireless Networks Matthew J. Miller and Nitin H. Vaidya University of Illinois at Urbana-Champaign BROADNETS October.
Rapid Development and Flexible Deployment of Adaptive Wireless Sensor Network Applications Chien-Liang Fok, Gruia-Catalin Roman, Chenyang Lu
Defense by Amit Saha March 25 th, 2004, Rice University ANTS : A Toolkit for Building and Dynamically Deploying Network Protocols David Wetherall, John.
CSE S. Tanimoto Lambda Calculus 1 Lambda Calculus What is the simplest functional language that is still Turing complete? Where do functional languages.
BitTorrent Nathan Marz Raylene Yung. BitTorrent BitTorrent consists of two protocols – Tracker HTTP protocol (THP) How an agent joins a swarm How an agent.
Programming With C.
Unit-1 Introduction Prepared by: Prof. Harish I Rathod
Dynamic Memory Allocation. Domain A subset of the total domain name space. A domain represents a level of the hierarchy in the Domain Name Space, and.
Data TypestMyn1 Data Types The type of a variable is not set by the programmer; rather, it is decided at runtime by PHP depending on the context in which.
Virtual Machines, Interpretation Techniques, and Just-In-Time Compilers Kostis Sagonas
SE424 Languages with Context A Block Structured Language.
Main Issues Three major issues that we are concerned with in sensor networks are – Clustering Routing and Security To be considered against the backdrop.
Ronny Krashinsky Erik Machnicki Software Cache Coherent Shared Memory under Split-C.
12/9/20151 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC Based in part on slides by Mattox.
Just Enough Type Theory or, Featherweight Java A Simple Formal Model of Objects Jonathan Aldrich
Types and Programming Languages Lecture 11 Simon Gay Department of Computing Science University of Glasgow 2006/07.
What’s Ahead for Embedded Software? (Wed) Gilsoo Kim
CS5205Semantics1 CS5205: Foundation in Programming Languages Semantics Static Semantics Dynamic Semantics Operational Semantics Big-step Small-Step Denotational.
ENEE150 – 0102 ANDREW GOFFIN Abstract Data Types.
Windows Programming Lecture 06. Data Types Classification Data types are classified in two categories that is, – those data types which stores decimal.
LLVM IR, File - Praakrit Pradhan. Overview The LLVM bitcode has essentially two things A bitstream container format Encoding of LLVM IR.
Sung-Dong Kim, Dept. of Computer Engineering, Hansung University Java - Introduction.
Lecture 3 Translation.
Chapter 4 Network Layer Computer Networking: A Top Down Approach 6th edition Jim Kurose, Keith Ross Addison-Wesley March 2012 CPSC 335 Data Communication.
Course Contents KIIT UNIVERSITY Sr # Major and Detailed Coverage Area
Programming Languages and Compilers (CS 421)
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
C Basics.
Design III Chapter 13 9/20/2018 Crowley OS Chap. 13.
ECE 544 Protocol Design Project 2016
Chapter 9 :: Subroutines and Control Abstraction
ECE 544 Protocol Design Project 2016
Frank Ng, Jud Porter, John Tat
Fundamentals of Programming
Subprograms and Programmer Defined Data Type
Semantic Analysis Chapter 6.
Assignments and Procs w/Params
CSE S. Tanimoto Lambda Calculus
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
Presentation transcript:

Type-Specialized Staged Programming with Process Separation Yu David Liu, State University of New York at Binghamton Christian Skalka, University of Vermont Scott Smith, Johns Hopkins University WGP’09 08/30/2009

〈 ML 〉 in a Nutshell A staging calculus  Programming abstractions to allow a program at certain stage to manipulate/generate code of the next stage  Familiar related work: macro languages, code generation systems Features of 〈 ML 〉 :  Process separation: no shared memory between stages  Type abstraction: one stage can refine types of the next  Types as values  Sound static type system

Source: General Purpose But with a Focus 〈 ML 〉 is a general-purpose staging calculus; related to MetaML-like languages 〈 ML 〉 is strongly motivated for programming resource- constrained embedded systems

Grand Challenges for Sensor Networks TELOSB mote, at Power Consumption Memory Consumption

Programming Without Staging uint32 self_addr; void init () { self_addr = addr_setup(); } void send (message_t msg) { msg.header.source = self_addr; … } void main { init(); while(true) {send(some_msg)}; } self_addr needs to be computed by mote (imagine a costly distributed address assignment protocol) memory space needed for self_addr Note: Just a Toy Example

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈 Stage Separation

void main { for (i=0; i<MAX; i++) { addr = getAddr(i); run (stagedcode (lift addr)); } void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } Staging at Work 〉 stagedcode = λ self_addr: 〈.uint32. 〉 〈 Hub Stage Execution

void main { while(true) {send(some_msg)}; } void send (message_t msg) { msg.header.source = 0xFF; … } Mote Stage Execution Staging at Work

Real World Applications In the real world, consider the computation of self_addr is in fact a computation of: A routing table: it can be entirely pre-computed (and highly optimized) at hub stage after initial deployment and stored in ROM A neighborhood table Environment information

Language Syntax v :: = constant | x | λ x: τ. e | 〈 e 〉 | {l 1 = v 1 ; …; l n = v n } | Λ t ≼ τ. e | τ e ::= v | ( τ ) e | e e | run e | lift e | {l 1 = e 1 ; …; l n = e n } | e.l | ref e | e :=e | !e | tlet t ≼ τ = e in e τ ::=primitive | τ → τ | 〈.τ. 〉 | {l 1 =τ 1 ; …; l n = τ n } | ref τ | t | Π t ≼ τ. e | type[τ]

Language Syntax v :: = constant | x | λ x: τ. e | 〈 e 〉 | {l 1 = v 1 ; …; l n = v n } | Λ t ≼ τ. e | τ e ::= v | ( τ ) e | e e | run e | lift e | {l 1 = e 1 ; …; l n = e n } | e.l | ref e | e :=e | !e | tlet t ≼ τ = e in e τ ::=primitive | τ → τ | 〈.τ. 〉 | {l 1 =τ 1 ; …; l n = τ n } | ref τ | t | Π t ≼ τ. e | type[τ]

Language Syntax v :: = constant | x | λ x: τ. e | 〈 e 〉 | {l 1 = v 1 ; …; l n = v n } | Λ t ≼ τ. e | τ e ::= v | ( τ ) e | e e | run e | lift e | {l 1 = e 1 ; …; l n = e n } | e.l | ref e | e :=e | !e | tlet t ≼ τ = e in e τ ::=primitive | τ → τ | 〈.τ. 〉 | {l 1 =τ 1 ; …; l n = τ n } | ref τ | t | Π t ≼ τ. e | type[τ]

Language Syntax v :: = constant | x | λ x: τ. e | 〈 e 〉 | {l 1 = v 1 ; …; l n = v n } | Λ t ≼ τ. e | τ e ::= v | ( τ ) e | e e | run e | lift e | {l 1 = e 1 ; …; l n = e n } | e.l | ref e | e :=e | !e | tlet t ≼ τ = e in e τ ::=primitive | τ → τ | 〈.τ. 〉 | {l 1 =τ 1 ; …; l n = τ n } | ref τ | t | Π t ≼ τ. e | type[τ]

Why Type Abstraction? In sensor networks, transmitting one bit consumes power similar to executing instructions! void send (message_t msg) { msg.header.source = self_addr; … } void main { while(true) {send(some_msg)}; } stagedcode = λ self_addr:. 〈 〉

Why Type Abstraction? void send (message_t msg) { msg.header.source := self_addr; … } void main { while(true) {send(some_msg)}; } stagedcode = λ self_addr:. 〈 〉 Λ t ≼ uint. stagedcode uint4 (lift addr) Each send saves the power of executing (32-4)* 800 instructions! F <: -Style Bounded Quantification

Why Types As Values? Common macro pattern in systems programming: # ifdef v typedef t uint8 else typedef t uint4 Macros as a (primitive) form of staging, i.e. t = if v then uint8 else uint4 Crucial for resource-constrained embedded systems:  “if there are at most 8 neighbors for each mote, use 3-bit integers to represent routing entries; otherwise if at most 16, use 4-bit integers.”  “if earthquake is frequent, use 8-byte double to record vibration; otherwise use 4-byte double.”

Type Checking First-Class Types Decidability: unrestricted use of first-class types often leads to undecidability Our simple solution: explicit upper bounds for type variables tlet t ≼ uint = if v then uint8 else uint4 in e When e is typed, t is typed as type[ uint ] in the context, meaning “ a type expression with uint as the upper bound”

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self the previous example in lambda calculus

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self a more realistic “send”

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self address type abstraction

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self header type abstraction

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self message type abstraction

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self cross-stage persistence of types is allowed!

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self tlet

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self tlet with bound abbreviated

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self more let

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self casting to a tlet-ed type

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self application of Λ term with subtyping

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self beyond F <: -- application argument not statically known

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send (if LARGE then uint8 else uint4) ht mt (radio mt) self arbitrary expressions as arguments however may lead to undecidablility

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self Our design: the arguments of Λ term application must be fully constructed

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self If ht or mt is inlined, the program still typechecks; but not if t is inlined! Our design: the arguments of Λ term application must be fully constructed

A Bigger Example let send = Λ addr_t ≼ uint. Λ message_header_t ≼ {src : addr_t; dest : addr_t}. Λ msg_t ≼ {header : message_header_t}. λ psend :. λ self : < λ addr : addr_t. λ msg : msg_t. msg.header.src := self; msg.header.dest := addr; psend msg > in tlet t ≼ uint = if LARGE then uint8 else uint4 in tlet ht = {flag : uint8; src : t; dest : t} in tlet mt = {header : ht; data : uint64} in let radio = Λ msg_t in let self = lift ((t)0xF) in send t ht mt (radio mt) self If ht or mt is inlined, the program still typechecks; but not if t is inlined! Our design: the arguments of Λ term application must be fully constructed Principle: expressivity with decidability

The Type System Type soundness proved via subject reduction and progress Future work: increasing precision for typing first- class type expressions, such as conditional types for those involved in branching

Related Work Flask (ICFP’08) Successfully implemented in a sensor network environment No static cross-stage type checking MetaML No type abstraction, no types as values Supports cross-stage persistence Meta programming Type abstraction/generic systems Dependent type systems

Conclusion and Future Work Conclusions: Staging is a crucial concept for modeling software deployment lifecycle Staging is particularly useful for reducing power consumption and memory consumption of embedded systems The importance of static type checking, type abstraction, and first-class types for embedded systems Ongoing and Future work: Developing a realistic sensor network language based on on top of TinyOS + nesC environment the effect of dynamic configuration More precise type checking; type inference

Thank you!