The document describes static name resolution in programming languages. It discusses how names are bound to declarations through lexical scoping and how references are resolved to declarations by following paths through a scope graph representation. It presents the concepts of scopes, declarations, references, resolution paths, imports, and parent scopes. It also discusses how name resolution can be formalized using a calculus based on scope graphs, separation reachability and visibility, and how this supports name resolution, disambiguation, and program transformations.
This document provides an outline and overview of dynamic semantics and operational semantics. It discusses defining the meaning of programs through execution and transition systems. It introduces DynSem, a domain-specific language for specifying dynamic semantics in a modular way. DynSem specifications generate interpreters from language definitions. The document uses examples from arithmetic expressions and a language with boxes to illustrate DynSem specifications.
This document discusses type-dependent name resolution in programming languages. It notes that sometimes type information is needed before name resolution can be performed, such as when resolving names in records where the record fields depend on the types. It gives an example where a program defines two records A and B, with B containing a field of type A, and names must be resolved through the record types. The document suggests that name resolution and type checking/inference can often be done in either order for languages, but type information is sometimes necessary for resolving some names.
This document discusses term rewriting and provides examples of how rewrite rules can be used to transform terms. Key points include:
- Rewrite rules define pattern matching and substitution to transform terms from a left-hand side to a right-hand side.
- Examples show desugaring language constructs like if-then statements, constant folding arithmetic expressions, and mapping/zipping lists with strategies as parameters to rules.
- Terms can represent programming language syntax and semantics domains. Signatures define the structure of terms.
- Rewriting systems provide a declarative way to define program transformations and semantic definitions through rewrite rules and strategies.
Introduction - Imperative and Object-Oriented LanguagesGuido Wachsmuth
This document provides an overview of imperative and object-oriented languages. It discusses the properties of imperative languages like state, statements, control flow, procedures and types. It then covers object-oriented concepts like objects, messages, classes, inheritance and polymorphism. Examples are given in various languages like C, Java bytecode, x86 assembly to illustrate concepts like variables, expressions, functions and object-oriented features. Finally, it provides an outlook on upcoming lectures covering declarative language definition.
The document discusses static analysis and error checking in compiler construction. It introduces key concepts like parsing source code, performing static semantic checks, and generating machine code. Specific techniques covered include name analysis, type systems, formal semantics, and testing static analysis. Examples are provided using Tiger, a simple imperative language, to illustrate type rules and name binding. The document also discusses theoretical foundations in formal language theory and decidability/complexity.
Declarative Semantics Definition - Term RewritingGuido Wachsmuth
This document discusses term rewriting and its applications in compiler construction. It covers term rewriting systems, rewrite rules that transform terms, and rewrite strategies that control rule application. Examples are provided for desugaring code using rewrite rules and constant folding arithmetic expressions using rewrite rules and strategies. Stratego is presented as a domain-specific language for program transformation based on term rewriting.
The document discusses lexical analysis and regular languages. It begins with an overview of lexical analysis and its components, including regular languages defined via regular grammars, regular expressions, and finite state automata. It then covers the equivalence between these formalisms for describing regular languages and how to construct a nondeterministic finite automaton from a regular expression.
Compiler Components and their Generators - Lexical AnalysisGuido Wachsmuth
The document discusses lexical analysis in compiler construction, including an overview of the topics covered such as regular languages represented as regular grammars, regular expressions, and finite state automata. It also discusses the equivalence between these formalisms and techniques for constructing tools for lexical analysis.
This document provides an outline and overview of dynamic semantics and operational semantics. It discusses defining the meaning of programs through execution and transition systems. It introduces DynSem, a domain-specific language for specifying dynamic semantics in a modular way. DynSem specifications generate interpreters from language definitions. The document uses examples from arithmetic expressions and a language with boxes to illustrate DynSem specifications.
This document discusses type-dependent name resolution in programming languages. It notes that sometimes type information is needed before name resolution can be performed, such as when resolving names in records where the record fields depend on the types. It gives an example where a program defines two records A and B, with B containing a field of type A, and names must be resolved through the record types. The document suggests that name resolution and type checking/inference can often be done in either order for languages, but type information is sometimes necessary for resolving some names.
This document discusses term rewriting and provides examples of how rewrite rules can be used to transform terms. Key points include:
- Rewrite rules define pattern matching and substitution to transform terms from a left-hand side to a right-hand side.
- Examples show desugaring language constructs like if-then statements, constant folding arithmetic expressions, and mapping/zipping lists with strategies as parameters to rules.
- Terms can represent programming language syntax and semantics domains. Signatures define the structure of terms.
- Rewriting systems provide a declarative way to define program transformations and semantic definitions through rewrite rules and strategies.
Introduction - Imperative and Object-Oriented LanguagesGuido Wachsmuth
This document provides an overview of imperative and object-oriented languages. It discusses the properties of imperative languages like state, statements, control flow, procedures and types. It then covers object-oriented concepts like objects, messages, classes, inheritance and polymorphism. Examples are given in various languages like C, Java bytecode, x86 assembly to illustrate concepts like variables, expressions, functions and object-oriented features. Finally, it provides an outlook on upcoming lectures covering declarative language definition.
The document discusses static analysis and error checking in compiler construction. It introduces key concepts like parsing source code, performing static semantic checks, and generating machine code. Specific techniques covered include name analysis, type systems, formal semantics, and testing static analysis. Examples are provided using Tiger, a simple imperative language, to illustrate type rules and name binding. The document also discusses theoretical foundations in formal language theory and decidability/complexity.
Declarative Semantics Definition - Term RewritingGuido Wachsmuth
This document discusses term rewriting and its applications in compiler construction. It covers term rewriting systems, rewrite rules that transform terms, and rewrite strategies that control rule application. Examples are provided for desugaring code using rewrite rules and constant folding arithmetic expressions using rewrite rules and strategies. Stratego is presented as a domain-specific language for program transformation based on term rewriting.
The document discusses lexical analysis and regular languages. It begins with an overview of lexical analysis and its components, including regular languages defined via regular grammars, regular expressions, and finite state automata. It then covers the equivalence between these formalisms for describing regular languages and how to construct a nondeterministic finite automaton from a regular expression.
Compiler Components and their Generators - Lexical AnalysisGuido Wachsmuth
The document discusses lexical analysis in compiler construction, including an overview of the topics covered such as regular languages represented as regular grammars, regular expressions, and finite state automata. It also discusses the equivalence between these formalisms and techniques for constructing tools for lexical analysis.
Slides for invited talk at Dynamic Languages Symposium (DLS'15) at SPLASH 2015 in Pittsburgh
http://2015.splashcon.org/event/dls2015-papers-declare-your-language
In the Language Designer’s Workbench project we are extending the Spoofax Language Workbench with meta-languages to declaratively specify the syntax, name binding rules, type rules, and operational semantics of a programming language design such that a variety of artifacts including parsers, static analyzers, interpreters, and IDE editor services can be derived and properties can be verified automatically. In this presentation I will talk about declarative specification for two aspects of language design: syntax and name binding.
First, I discuss the idea of declarative syntax definition as supported by grammar formalisms based on generalized parsing using the SDF3 syntax definition formalism as example. With SDF3, the language designer defines syntax in terms of productions and declarative disambiguation rules. This requires understanding a language in term of (tree) structure instead of the operational implementation of parsers. As a result, syntax definitions can be used for a range of language processors including parsers, formatters, syntax coloring, outline view, syntactic completion.
Second, I discuss our recent work on the declarative specification of name binding rules, that takes inspiration from declarative syntax definition. The NaBL name binding language supports definition of name binding rules in terms of its fundamental concepts: declarations, references, scopes, and imports. I will present the theory of name resolution that we have recently developed to provide a semantics for name binding languages such as NaBL.
Compiler Components and their Generators - Traditional Parsing AlgorithmsGuido Wachsmuth
This document discusses parsing algorithms for compilers. It begins with an overview of topics to be covered, including lexical analysis, parsing algorithms like predictive and LR parsing, grammar classes, and an assignment on implementing a MiniJava compiler. It then covers predictive parsing in more detail, including how to generate parsing tables from grammars and how to use these tables in a predictive parsing automaton. Finally, it discusses LR parsing and how it can handle issues like left recursion that predictive parsing cannot. It provides an example of an LR parsing step involving expression evaluation.
Declarative Semantics Definition - Static Analysis and Error CheckingGuido Wachsmuth
The document discusses static analysis and error checking in compiler construction. It covers several key topics:
- The static analysis process of parsing source code, checking for errors, and generating machine code.
- Name analysis, binding, and scoping during static checking and for editor services like refactoring and code generation.
- Testing static semantics including name binding, type systems, and constraints.
- Restricting context-free languages using static semantics and judgements of well-formedness and well-typedness.
- Formal type systems including those for Tiger language examples involving types, expressions, and scoping.
Dynamic Semantics Specification and Interpreter GenerationEelco Visser
(1) The document describes a domain specific language called DynSem for specifying dynamic semantics of programming languages. DynSem allows defining semantics in a modular way using semantic rules.
(2) DynSem specifications can be used to generate high-performance interpreters. The document outlines various language features that can be modeled in DynSem, including arithmetic, booleans, control flow, functions, and mutable state.
(3) DynSem specifications are composed of modules that import language signatures and define semantic rules over them. Rules are used to reduce expressions to values in an environment and store. This allows modeling features like variables, functions, and mutable boxes.
Declare Your Language: Syntactic (Editor) ServicesEelco Visser
Lecture 3 on compiler construction course on definition of lexical syntax and syntactic services that can be derived from syntax definitions such as formatting and syntactic completion
Declarative Syntax Definition - Grammars and TreesGuido Wachsmuth
This lecture lays the theoretic foundations for declarative syntax formalisms and syntax-based language processors, which we will discuss later in the course. We introduce the notions of formal languages, formal grammars, and syntax trees, starting from Chomsky's work on formal grammars as generative devices.
We start with a formal model of languages and investigate formal grammars and their derivation relations as finite models of infinite productivity. We further discuss several classes of formal grammars and their corresponding classes of formal languages. In a second step, we introduce the word problem, analyse its decidability and complexity for different classes of formal languages, and discuss consequences of this analysis on language processing. We conclude the lecture with a discussion about parse tree construction, abstract syntax trees, and ambiguities.
This document summarizes and discusses type checking algorithms for programming languages. It introduces constraint-based type checking, which separates type checking into constraint generation and constraint solving. This provides a more declarative way to specify type checkers. The document discusses using variables and constraints to represent types during type checking. It introduces NaBL2, a domain-specific language for writing constraint generators to specify name and type constraints for programming language static semantics. NaBL2 uses scope graphs to represent name binding structures and supports features like type equality, subtyping, and type-dependent name resolution through constraint rules. An example scope graph and constraint rule for let-bindings is provided.
This document discusses syntax definition and provides examples using various syntax definition formalisms including Backus-Naur Form (BNF), Extended Backus-Naur Form (EBNF), and SDF3. It introduces concepts of lexical syntax, context-free syntax, abstract syntax, disambiguation, and testing syntax definitions. Specific examples are provided for defining the syntax of an expression language using BNF, EBNF, and SDF3. Testing syntax definitions using Spoofax is also discussed with examples of test cases for lexical and context-free syntax.
This document provides an overview of LL parsing algorithms. It begins with a recap of formal language theory concepts like regular grammars, regular expressions, finite state automata, context-free grammars, derivation, and language generation. It then discusses predictive (recursive descent) parsing and LL parsing in particular. Key concepts covered include LL(k) grammars, filling the LL parsing table based on FIRST and FOLLOW sets, and using the table to perform LL parsing. An example grammar and its parsing table are provided to illustrate the process.
The document discusses formal grammars and their applications in language specification and parsing. It introduces key concepts such as formal grammars, derivation, terminal and non-terminal symbols, and different types of grammars including context-sensitive, context-free and regular grammars. It also discusses applications of formal grammars in parsing and how they relate to theoretical computer science concepts like decidability and complexity of the word problem for different grammar types.
Declare Your Language: Syntax DefinitionEelco Visser
This document provides information about syntax definition and the lab organization for a compiler construction course. It includes links to papers on declarative syntax definition and the SDF3 syntax definition formalism. It also provides details about submitting lab assignments through GitHub, including instructions to fork a repository template and submit solutions as pull requests. Grades will be published on a web lab and early feedback may be provided on pull requests and pushed changes.
The document discusses syntax definition in programming languages. It provides examples of lexical syntax, context-free syntax, abstract syntax trees, disambiguation, and testing syntax definitions using SDF3 and Spoofax. Key topics covered include regular expressions, Backus-Naur Form, Extended Backus-Naur Form, SDF3 syntax, Spoofax architecture for language implementation, and syntax processing tools like parsers, pretty-printers and compilers.
Compiler Construction | Lecture 9 | Constraint ResolutionEelco Visser
This document provides an overview of constraint resolution in the context of a compiler construction lecture. It discusses unification, which is the basis for many type inference and constraint solving approaches. It also describes separating type checking into constraint generation and constraint solving, and introduces a constraint language that integrates name resolution into constraint resolution through scope graph constraints. Finally, it discusses papers on further developments with this approach, including addressing expressiveness and staging issues in type systems through the Statix DSL for defining type systems.
Separation of Concerns in Language DefinitionEelco Visser
Slides for keynote at the Modularity 2014 conference in Lugano on April 23, 2014. (A considerable part of the talk consisted of live programming the syntax definition and name binding rules for a little language.)
What is "logic programming" and "constraint programming"
Prolog in a nutshell
How Prolog "makes pointers safe"
Why Prolog was the ultimate scripting language for AI (backtracking search, interpreters, and DSLs for free)
What is "functional-logic programming" (a taste of the programming language Mercury)
Video recording of the talk: http://youtu.be/Fhc7fPQF1iY
This document discusses imperative and object-oriented programming languages. It covers basic concepts like state, variables, expressions, assignments, and control flow in imperative languages. It also discusses procedures and functions, including passing parameters, stack frames, and recursion. Finally, it briefly mentions the differences between call by value and call by reference.
Top down parsers are more restricted than bottom up parsers. However, ANTLR uses a top-down parser. In this chapter parse tables and recursive descent parsers are described.
Scope Graphs: A fresh look at name binding in programming languagesEelco Visser
This document summarizes Eelco Visser's talk "Scope Graphs: A fresh look at name binding in programming languages" given at Curry On 2017 in Barcelona. It discusses using scope graphs to represent name binding and define declarative rules for name resolution in programming languages. Scope graphs connect references to their declarations through edges representing scopes, references, declarations, imports, and parent relationships. A calculus for name resolution uses these relationships to define constraints for well-formed paths and visibility/reachability of declarations. Scope graphs separate the representation of name binding from language-specific rules, enabling language-independent name resolution tools.
Presentation of GetTogether on Functional ProgrammingFilip De Sutter
This document discusses functional programming and provides examples in Haskell, F# and C#. It begins with an introduction to the author and their background in functional programming languages like Prolog, Haskell and F#. It then covers various functional programming concepts like recursion, pattern matching, avoiding side effects, strong typing and type inference. Examples are provided for sorting lists, calculating factorials and other common functional programming tasks. The document emphasizes the declarative nature of functional programming and compares approaches in Haskell, F# and C#.
Slides for invited talk at Dynamic Languages Symposium (DLS'15) at SPLASH 2015 in Pittsburgh
http://2015.splashcon.org/event/dls2015-papers-declare-your-language
In the Language Designer’s Workbench project we are extending the Spoofax Language Workbench with meta-languages to declaratively specify the syntax, name binding rules, type rules, and operational semantics of a programming language design such that a variety of artifacts including parsers, static analyzers, interpreters, and IDE editor services can be derived and properties can be verified automatically. In this presentation I will talk about declarative specification for two aspects of language design: syntax and name binding.
First, I discuss the idea of declarative syntax definition as supported by grammar formalisms based on generalized parsing using the SDF3 syntax definition formalism as example. With SDF3, the language designer defines syntax in terms of productions and declarative disambiguation rules. This requires understanding a language in term of (tree) structure instead of the operational implementation of parsers. As a result, syntax definitions can be used for a range of language processors including parsers, formatters, syntax coloring, outline view, syntactic completion.
Second, I discuss our recent work on the declarative specification of name binding rules, that takes inspiration from declarative syntax definition. The NaBL name binding language supports definition of name binding rules in terms of its fundamental concepts: declarations, references, scopes, and imports. I will present the theory of name resolution that we have recently developed to provide a semantics for name binding languages such as NaBL.
Compiler Components and their Generators - Traditional Parsing AlgorithmsGuido Wachsmuth
This document discusses parsing algorithms for compilers. It begins with an overview of topics to be covered, including lexical analysis, parsing algorithms like predictive and LR parsing, grammar classes, and an assignment on implementing a MiniJava compiler. It then covers predictive parsing in more detail, including how to generate parsing tables from grammars and how to use these tables in a predictive parsing automaton. Finally, it discusses LR parsing and how it can handle issues like left recursion that predictive parsing cannot. It provides an example of an LR parsing step involving expression evaluation.
Declarative Semantics Definition - Static Analysis and Error CheckingGuido Wachsmuth
The document discusses static analysis and error checking in compiler construction. It covers several key topics:
- The static analysis process of parsing source code, checking for errors, and generating machine code.
- Name analysis, binding, and scoping during static checking and for editor services like refactoring and code generation.
- Testing static semantics including name binding, type systems, and constraints.
- Restricting context-free languages using static semantics and judgements of well-formedness and well-typedness.
- Formal type systems including those for Tiger language examples involving types, expressions, and scoping.
Dynamic Semantics Specification and Interpreter GenerationEelco Visser
(1) The document describes a domain specific language called DynSem for specifying dynamic semantics of programming languages. DynSem allows defining semantics in a modular way using semantic rules.
(2) DynSem specifications can be used to generate high-performance interpreters. The document outlines various language features that can be modeled in DynSem, including arithmetic, booleans, control flow, functions, and mutable state.
(3) DynSem specifications are composed of modules that import language signatures and define semantic rules over them. Rules are used to reduce expressions to values in an environment and store. This allows modeling features like variables, functions, and mutable boxes.
Declare Your Language: Syntactic (Editor) ServicesEelco Visser
Lecture 3 on compiler construction course on definition of lexical syntax and syntactic services that can be derived from syntax definitions such as formatting and syntactic completion
Declarative Syntax Definition - Grammars and TreesGuido Wachsmuth
This lecture lays the theoretic foundations for declarative syntax formalisms and syntax-based language processors, which we will discuss later in the course. We introduce the notions of formal languages, formal grammars, and syntax trees, starting from Chomsky's work on formal grammars as generative devices.
We start with a formal model of languages and investigate formal grammars and their derivation relations as finite models of infinite productivity. We further discuss several classes of formal grammars and their corresponding classes of formal languages. In a second step, we introduce the word problem, analyse its decidability and complexity for different classes of formal languages, and discuss consequences of this analysis on language processing. We conclude the lecture with a discussion about parse tree construction, abstract syntax trees, and ambiguities.
This document summarizes and discusses type checking algorithms for programming languages. It introduces constraint-based type checking, which separates type checking into constraint generation and constraint solving. This provides a more declarative way to specify type checkers. The document discusses using variables and constraints to represent types during type checking. It introduces NaBL2, a domain-specific language for writing constraint generators to specify name and type constraints for programming language static semantics. NaBL2 uses scope graphs to represent name binding structures and supports features like type equality, subtyping, and type-dependent name resolution through constraint rules. An example scope graph and constraint rule for let-bindings is provided.
This document discusses syntax definition and provides examples using various syntax definition formalisms including Backus-Naur Form (BNF), Extended Backus-Naur Form (EBNF), and SDF3. It introduces concepts of lexical syntax, context-free syntax, abstract syntax, disambiguation, and testing syntax definitions. Specific examples are provided for defining the syntax of an expression language using BNF, EBNF, and SDF3. Testing syntax definitions using Spoofax is also discussed with examples of test cases for lexical and context-free syntax.
This document provides an overview of LL parsing algorithms. It begins with a recap of formal language theory concepts like regular grammars, regular expressions, finite state automata, context-free grammars, derivation, and language generation. It then discusses predictive (recursive descent) parsing and LL parsing in particular. Key concepts covered include LL(k) grammars, filling the LL parsing table based on FIRST and FOLLOW sets, and using the table to perform LL parsing. An example grammar and its parsing table are provided to illustrate the process.
The document discusses formal grammars and their applications in language specification and parsing. It introduces key concepts such as formal grammars, derivation, terminal and non-terminal symbols, and different types of grammars including context-sensitive, context-free and regular grammars. It also discusses applications of formal grammars in parsing and how they relate to theoretical computer science concepts like decidability and complexity of the word problem for different grammar types.
Declare Your Language: Syntax DefinitionEelco Visser
This document provides information about syntax definition and the lab organization for a compiler construction course. It includes links to papers on declarative syntax definition and the SDF3 syntax definition formalism. It also provides details about submitting lab assignments through GitHub, including instructions to fork a repository template and submit solutions as pull requests. Grades will be published on a web lab and early feedback may be provided on pull requests and pushed changes.
The document discusses syntax definition in programming languages. It provides examples of lexical syntax, context-free syntax, abstract syntax trees, disambiguation, and testing syntax definitions using SDF3 and Spoofax. Key topics covered include regular expressions, Backus-Naur Form, Extended Backus-Naur Form, SDF3 syntax, Spoofax architecture for language implementation, and syntax processing tools like parsers, pretty-printers and compilers.
Compiler Construction | Lecture 9 | Constraint ResolutionEelco Visser
This document provides an overview of constraint resolution in the context of a compiler construction lecture. It discusses unification, which is the basis for many type inference and constraint solving approaches. It also describes separating type checking into constraint generation and constraint solving, and introduces a constraint language that integrates name resolution into constraint resolution through scope graph constraints. Finally, it discusses papers on further developments with this approach, including addressing expressiveness and staging issues in type systems through the Statix DSL for defining type systems.
Separation of Concerns in Language DefinitionEelco Visser
Slides for keynote at the Modularity 2014 conference in Lugano on April 23, 2014. (A considerable part of the talk consisted of live programming the syntax definition and name binding rules for a little language.)
What is "logic programming" and "constraint programming"
Prolog in a nutshell
How Prolog "makes pointers safe"
Why Prolog was the ultimate scripting language for AI (backtracking search, interpreters, and DSLs for free)
What is "functional-logic programming" (a taste of the programming language Mercury)
Video recording of the talk: http://youtu.be/Fhc7fPQF1iY
This document discusses imperative and object-oriented programming languages. It covers basic concepts like state, variables, expressions, assignments, and control flow in imperative languages. It also discusses procedures and functions, including passing parameters, stack frames, and recursion. Finally, it briefly mentions the differences between call by value and call by reference.
Top down parsers are more restricted than bottom up parsers. However, ANTLR uses a top-down parser. In this chapter parse tables and recursive descent parsers are described.
Scope Graphs: A fresh look at name binding in programming languagesEelco Visser
This document summarizes Eelco Visser's talk "Scope Graphs: A fresh look at name binding in programming languages" given at Curry On 2017 in Barcelona. It discusses using scope graphs to represent name binding and define declarative rules for name resolution in programming languages. Scope graphs connect references to their declarations through edges representing scopes, references, declarations, imports, and parent relationships. A calculus for name resolution uses these relationships to define constraints for well-formed paths and visibility/reachability of declarations. Scope graphs separate the representation of name binding from language-specific rules, enabling language-independent name resolution tools.
Presentation of GetTogether on Functional ProgrammingFilip De Sutter
This document discusses functional programming and provides examples in Haskell, F# and C#. It begins with an introduction to the author and their background in functional programming languages like Prolog, Haskell and F#. It then covers various functional programming concepts like recursion, pattern matching, avoiding side effects, strong typing and type inference. Examples are provided for sorting lists, calculating factorials and other common functional programming tasks. The document emphasizes the declarative nature of functional programming and compares approaches in Haskell, F# and C#.
Declare Your Language: Name ResolutionEelco Visser
Scope graphs are used to represent the binding information in programs. They provide a language-independent representation of name resolution that can be used to conduct and represent the results of name resolution. Separating the representation of resolved programs from the declarative rules that define name binding allows language-independent tooling to be developed for name resolution and other tasks.
This document discusses strategies for scaling declarative language specifications to full-featured languages and real-world applications. One strategy is to identify a "core" language and translate new features down to the core features. Forwarding in attribute grammars supports both explicit and implicit specification of semantics via translation. Extensible language frameworks allow for pluggable domain-specific language extensions with their own syntax, analysis, and optimizations. Composable language specifications are needed for extensible languages, but modular analysis is also required to ensure safe composability of extensions.
Much of the early work on parameterized complexity considered the solution size as the parameter when parameterizing optimization problems, with a possible exception of treewidth. This talk will survey results and open problems on *alternate parameterizations*, where the parameter is typically some structure of the input or the distance of the output size from a guarantee.
Compiler Construction | Lecture 8 | Type ConstraintsEelco Visser
This lecture covers type checking with constraints. It introduces the NaBL2 meta-language for writing type specifications as constraint generators that map a program to constraints. The constraints are then solved to determine if a program is well-typed. NaBL2 supports defining name binding and type structures through scope graphs and constraints over names, types, and scopes. Examples show type checking patterns in NaBL2 including variables, functions, records, and name spaces.
Using Language Oriented Programming to Execute Computations on the GPUSkills Matter
F# has a number of features that support language oriented programming (LOP) – the ability to create an abstract description of a problem then have this description executed in another environment. In this talk we’ll look at the design of an F# library that uses LOP techniques to a user execute matrix calculations either on the CPU or GPU. We’ll examine the features that F# provides to support this technique. We’ll start by taking a look at union types and active patterns, and then we’ll see how these are used by F#’s quotation system to give access to an abstract description of functions. Finally, we’ll see how these descriptions of functions can then be translated into computations the GPU understands and executed.
TI1220 Lecture 8: Traits & Type ParameterizationEelco Visser
Traits allow code reuse through mixing in. Traits can contain fields, methods, and act as types. When mixed into classes, traits are linearly ordered and calls to super are dispatched accordingly. This avoids problems with multiple inheritance by ensuring there is always a single linearization of supertypes. The example code defines classes and traits for animals with traits for properties like being furry or having legs. It demonstrates how trait mixing and method overriding works.
2024.03.22 - Mike Heddes - Introduction to Hyperdimensional Computing.pdfAdvanced-Concepts-Team
Presentation in Science Coffee of the Advanced Concepts Team of the European Space Agency.
Date: 22.03.2024
Speaker: Mike Heddes (University of California, Irvine)
Topic: Introduction to Hyperdimensional Computing
Abstract:
Hyperdimensional computing (HD), also known as vector symbolic architectures (VSA), is a computing framework capable of forming compositional distributed representations. HD/VSA forms a "concept space" by exploiting the geometry and algebra of high-dimensional spaces. The central idea is to represent information with randomly generated vectors, called hypervectors. Together with a set of operations on these hypervectors, HD/VSA can represent compositional structures, which, in turn, enables features such as reasoning by analogy and cognitive computing. In this introductory talk, I will introduce the high-dimensional spaces and the fundamental operations on hypervectors. I will then cover applications of HD/VSA such as reasoning by analogy and graph classification.
This document discusses various greedy algorithms, including Dijkstra's algorithm for finding shortest paths in graphs. It provides details on Dijkstra's algorithm, including its greedy approach, proof of correctness, and efficient implementations using priority queues. It also discusses applications of shortest path algorithms and how the techniques extend to related problems involving closed semirings rather than just numbers.
The document discusses several topics in natural language processing including distributional semantics, language models, word embeddings, and neural network models like word2vec. It introduces techniques for distributional semantics using distributional properties of words from large datasets. Language models are discussed including n-gram models and language class models that incorporate word classes. Word embedding techniques like word2vec are introduced for generating word vectors using neural networks.
Fosdem 2013 petra selmer flexible querying of graph dataPetra Selmer
These are the slides from a talk I presented at the Graph Processing room at FOSDEM 2013, in which I discussed my PhD topic: a query language allowing for the flexible querying of complex paths within graph structured data
This document provides an overview of natural language processing (NLP) including the linguistic basis of NLP, common NLP problems and approaches, sources of NLP data, and steps to develop an NLP system. It discusses tokenization, part-of-speech tagging, parsing, machine learning approaches like naive Bayes classification and dependency parsing, measuring word similarity, and distributional semantics. The document also provides advice on going from research to production systems and notes areas not covered like machine translation and deep learning methods.
Querying your database in natural language was a presentation done during PyData Silicon Valley 2014, based on the quepy software project. More information at:
http://pydata.org/sv2014/abstracts/#197
https://github.com/machinalis/quepy
Querying your database in natural language by Daniel Moisset PyData SV 2014PyData
Most end users can't write a database query, and yet, they often have the need to access information that keyword-based searches can't retrieve precisely. Lately, there's been an explosion of proprietary Natural Language Interfaces to knowledge databases, like Siri, Google Now and Wolfram Alpha. On the open side, huge knowledge bases like DBpedia and Freebase exists, but access to them is typically limited to using formal database query languages. We implemented Quepy as an approach to provide a solution for this problem. Quepy is an open source framework to transform Natural Language questions into semantic database queries that can be used with popular knowledge databases like, for example, DBPedia and Freebase. So instead of requiring end users to learn to write some query language, a Quepy Application can fills the gap, allowing end users to make their queries in "plain English". In this talk we would discuss the techniques used in Quepy, what additional work can be done, and its limitations.
The document discusses what's new in Perl 5.14, including new syntax features like given and (?^...) switches, improvements to regular expressions with modifiers like /a and /r, and changes to how arrays and hashes are handled when referenced. It also mentions bug fixes, performance enhancements, and new modules/pragmas in Perl 5.14. The document encourages users to upgrade from older versions of Perl like 5.10 due to ending of support.
The document discusses the history and development of the Haskell programming language over 15 years. It summarizes key events like the initial meeting that kicked off Haskell in 1987, the release of the first Haskell report in 1990, and the standardization of Haskell 98. It also reflects on important aspects of Haskell like laziness, monads, and the process of language design by committee and community.
The document describes Dedalo, a system that automatically explains clusters of data by traversing linked data to find explanations. It evaluates different heuristics for guiding the traversal, finding that entropy and conditional entropy outperform other measures by reducing redundancy and search time. Experiments on authorship clusters, publication clusters, and library book borrowings demonstrate Dedalo's ability to discover explanatory linked data patterns within a limited domain. Future work includes extending Dedalo to handle more complex datasets by addressing issues such as sameAs linking and use of literals.
The document discusses the benefits of declarative programming using Scala. It provides examples of implementing algorithms and data structures declaratively in Scala. It also discusses the history and future of Scala, as well as how Scala encourages thinking about programs as transformations rather than changes to memory.
Ineluctable modality of the distributed systems knowledge in distributed systems. Uncertainty is what makes reasoning about distributed systems difficult. Protocols are just mechanisms to ensure that a group has shared knowledge of a fact by climbing the hierarchy from someone knowing to common knowledge. Common knowledge of initially undetermined facts is not attainable in any distributed system where communication is not guaranteed.
This document discusses syntactic editor services including formatting, syntax coloring, and syntactic completion. It describes how syntactic completion can be provided generically based on a syntax definition. The document also discusses how context-free grammars can be extended with templates to specify formatting layout when pretty-printing abstract syntax trees to text. Templates are used to insert whitespace, line breaks, and indentation to produce readable output.
This document provides an overview of parsing in compiler construction. It discusses context-free grammars and how they are used to generate sentences and parse trees through derivations. It also covers ambiguity that can arise from grammars and various grammar transformations used to eliminate ambiguity, including defining associativity and priority. The dangling else problem is presented as an example of an ambiguous grammar.
This document provides an overview of the Lecture 2 on Declarative Syntax Definition for the CS4200 Compiler Construction course. The lecture covers the specification of syntax definition from which parsers can be derived, the perspective on declarative syntax definition using SDF, and reading material on the SDF3 syntax definition formalism and papers on testing syntax definitions and declarative syntax. It also discusses what syntax is, both in linguistics and programming languages, and how programs can be described in terms of syntactic categories and language constructs. An example Tiger program for solving the n-queens problem is presented to illustrate syntactic categories in Tiger.
This document provides an overview of the CS4200 Compiler Construction course at TU Delft. It discusses the course organization, structure, and assessment. The course is split into two parts - CS4200-A which covers concepts and techniques through lectures, papers, and homework assignments, and CS4200-B which involves building a compiler for a subset of Java as a semester-long project. Students will use the Spoofax language workbench to implement their compiler and will submit assignments through a private GitLab repository.
A Direct Semantics of Declarative Disambiguation RulesEelco Visser
This document discusses research into providing a direct semantics for declarative disambiguation of expression grammars. It aims to define what disambiguation rules mean, ensure they are safe and complete, and provide an effective implementation strategy. The document outlines key research questions around the meaning, safety, completeness and coverage of disambiguation rules. It also presents contributions around using subtree exclusion patterns to define safe and complete disambiguation for classes of expression grammars, and implementing this in SDF3.
Declarative Type System Specification with StatixEelco Visser
In this talk I present the design of Statix, a new constraint-based language for the executable specification of type systems. Statix specifications consist of predicates that define the well-formedness of language constructs in terms of built-in and user-defined constraints. Statix has a declarative semantics that defines whether a model satisfies a constraint. The operational semantics of Statix is defined as a sound constraint solving algorithm that searches for a solution for a constraint. The aim of the design is that Statix users can ignore the execution order of constraint solving and think in terms of the declarative semantics.
A distinctive feature of Statix is its use of scope graphs, a language parametric framework for the representation and querying of the name binding facts in programs. Since types depend on name resolution and name resolution may depend on types, it is typically not possible to construct the entire scope graph of a program before type constraint resolution. In (algorithmic) type system specifications this leads to explicit staging of the construction and querying of the type environment (class table, symbol table). Statix automatically stages the construction of the scope graph of a program such that queries are never executed when their answers may be affected by future scope graph extension. In the talk, I will explain the design of Statix by means of examples.
https://eelcovisser.org/post/309/declarative-type-system-specification-with-statix
Compiler Construction | Lecture 17 | Beyond Compiler ConstructionEelco Visser
Compiler construction techniques are applied beyond general-purpose languages through domain-specific languages (DSLs). The document discusses several DSLs developed using Spoofax including:
- WebDSL for web programming with sub-languages for entities, queries, templates, and access control.
- IceDust for modeling information systems with derived values computed on-demand, incrementally, or eventually consistently.
- PixieDust for client-side web programming with views as derived values updated incrementally.
- PIE for defining software build pipelines as tasks with dynamic dependencies computed incrementally.
The document also outlines several research challenges in compiler construction like high-level declarative language definition, verification of
Domain Specific Languages for Parallel Graph AnalytiX (PGX)Eelco Visser
This document discusses domain-specific languages (DSLs) for parallel graph analytics using PGX. It describes how DSLs allow users to implement graph algorithms and queries using high-level languages that are then compiled and optimized to run efficiently on PGX. Examples of DSL optimizations like multi-source breadth-first search are provided. The document also outlines the extensible compiler architecture used for DSLs, which can generate code for different backends like shared memory or distributed memory.
Compiler Construction | Lecture 15 | Memory ManagementEelco Visser
The document discusses different memory management techniques:
1. Reference counting counts the number of pointers to each record and deallocates records with a count of 0.
2. Mark and sweep marks all reachable records from program roots and sweeps unmarked records, adding them to a free list.
3. Copying collection copies reachable records to a "to" space, allowing the original "from" space to be freed without fragmentation.
4. Generational collection focuses collection on younger object generations more frequently to improve efficiency.
Compiler Construction | Lecture 14 | InterpretersEelco Visser
This document summarizes a lecture on interpreters for programming languages. It discusses how operational semantics can be used to define the meaning of a program through state transitions in an interpreter. It provides examples of defining the semantics of a simple language using DynSem, a domain-specific language for specifying operational semantics. DynSem specifications can be compiled to interpreters that execute programs in the defined language.
Compiler Construction | Lecture 13 | Code GenerationEelco Visser
The document discusses code generation and optimization techniques, describing compilation schemas that define how language constructs are translated to target code patterns, and covers topics like ensuring correctness of generated code through type checking and verification of static constraints on the target format. It also provides examples of compilation schemas for Tiger language constructs like arithmetic expressions and control flow and discusses generating nested functions.
Compiler Construction | Lecture 12 | Virtual MachinesEelco Visser
The document discusses the architecture of the Java Virtual Machine (JVM). It describes how the JVM uses threads, a stack, heap, and method area. It explains JVM control flow through bytecode instructions like goto, and how the operand stack is used to perform operations and hold method arguments and return values.
Compiler Construction | Lecture 7 | Type CheckingEelco Visser
This document summarizes a lecture on type checking. It discusses using constraints to separate the language-specific type checking rules from the language-independent solving algorithm. Constraint-based type checking collects constraints as it traverses the AST, then solves the constraints in any order. This allows type information to be learned gradually and avoids issues with computation order.
Compiler Construction | Lecture 6 | Introduction to Static AnalysisEelco Visser
Lecture introducing the need for static analysis in addition to parsing, the complications caused by names, and an introduction to name resolution with scope graphs
Compiler Construction | Lecture 4 | Parsing Eelco Visser
This lecture covers parsing and turning syntax definitions into parsers. It discusses context-free grammars and derivations. Grammars can be ambiguous, allowing multiple parse trees for a sentence. Grammar transformations like disambiguation, eliminating left recursion, and left factoring can address issues while preserving the language. Associativity and priority can be defined through transformations. The reading material covers parsing schemata, classical compiler textbooks, and papers on disambiguation filters and parsing algorithms.
Compiler Construction | Lecture 3 | Syntactic Editor ServicesEelco Visser
The document discusses syntactic editor services for programming languages. It covers formatting specifications that define how abstract syntax trees are mapped to text using templates. It also discusses syntactic completion, which proposes valid completions in an editor by using the syntax definition. The lecture focuses on defining lexical and syntactic syntax for Tiger using SDF, and generating editor services like formatting and coloring from the syntax definitions.
Compiler Construction | Lecture 2 | Declarative Syntax DefinitionEelco Visser
The document describes a lecture on declarative syntax definition. It discusses the perspective on declarative syntax definition explained in an Onward! 2010 essay. It also mentions an OOPSLA 2011 paper that introduced the SPoofax Testing (SPT) language used in the section on testing syntax definitions. Finally, it provides a link to documentation on the SDF3 syntax definition formalism.
Essentials of Automations: Exploring Attributes & Automation ParametersSafe Software
Building automations in FME Flow can save time, money, and help businesses scale by eliminating data silos and providing data to stakeholders in real-time. One essential component to orchestrating complex automations is the use of attributes & automation parameters (both formerly known as “keys”). In fact, it’s unlikely you’ll ever build an Automation without using these components, but what exactly are they?
Attributes & automation parameters enable the automation author to pass data values from one automation component to the next. During this webinar, our FME Flow Specialists will cover leveraging the three types of these output attributes & parameters in FME Flow: Event, Custom, and Automation. As a bonus, they’ll also be making use of the Split-Merge Block functionality.
You’ll leave this webinar with a better understanding of how to maximize the potential of automations by making use of attributes & automation parameters, with the ultimate goal of setting your enterprise integration workflows up on autopilot.
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving
What began over 115 years ago as a supplier of precision gauges to the automotive industry has evolved into being an industry leader in the manufacture of product branding, automotive cockpit trim and decorative appliance trim. Value-added services include in-house Design, Engineering, Program Management, Test Lab and Tool Shops.
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfChart Kalyan
A Mix Chart displays historical data of numbers in a graphical or tabular form. The Kalyan Rajdhani Mix Chart specifically shows the results of a sequence of numbers over different periods.
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...Fwdays
Direct losses from downtime in 1 minute = $5-$10 thousand dollars. Reputation is priceless.
As part of the talk, we will consider the architectural strategies necessary for the development of highly loaded fintech solutions. We will focus on using queues and streaming to efficiently work and manage large amounts of data in real-time and to minimize latency.
We will focus special attention on the architectural patterns used in the design of the fintech system, microservices and event-driven architecture, which ensure scalability, fault tolerance, and consistency of the entire system.
Fueling AI with Great Data with Airbyte WebinarZilliz
This talk will focus on how to collect data from a variety of sources, leveraging this data for RAG and other GenAI use cases, and finally charting your course to productionalization.
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...DanBrown980551
This LF Energy webinar took place June 20, 2024. It featured:
-Alex Thornton, LF Energy
-Hallie Cramer, Google
-Daniel Roesler, UtilityAPI
-Henry Richardson, WattTime
In response to the urgency and scale required to effectively address climate change, open source solutions offer significant potential for driving innovation and progress. Currently, there is a growing demand for standardization and interoperability in energy data and modeling. Open source standards and specifications within the energy sector can also alleviate challenges associated with data fragmentation, transparency, and accessibility. At the same time, it is crucial to consider privacy and security concerns throughout the development of open source platforms.
This webinar will delve into the motivations behind establishing LF Energy’s Carbon Data Specification Consortium. It will provide an overview of the draft specifications and the ongoing progress made by the respective working groups.
Three primary specifications will be discussed:
-Discovery and client registration, emphasizing transparent processes and secure and private access
-Customer data, centering around customer tariffs, bills, energy usage, and full consumption disclosure
-Power systems data, focusing on grid data, inclusive of transmission and distribution networks, generation, intergrid power flows, and market settlement data
Monitoring and Managing Anomaly Detection on OpenShift.pdfTosin Akinosho
Monitoring and Managing Anomaly Detection on OpenShift
Overview
Dive into the world of anomaly detection on edge devices with our comprehensive hands-on tutorial. This SlideShare presentation will guide you through the entire process, from data collection and model training to edge deployment and real-time monitoring. Perfect for those looking to implement robust anomaly detection systems on resource-constrained IoT/edge devices.
Key Topics Covered
1. Introduction to Anomaly Detection
- Understand the fundamentals of anomaly detection and its importance in identifying unusual behavior or failures in systems.
2. Understanding Edge (IoT)
- Learn about edge computing and IoT, and how they enable real-time data processing and decision-making at the source.
3. What is ArgoCD?
- Discover ArgoCD, a declarative, GitOps continuous delivery tool for Kubernetes, and its role in deploying applications on edge devices.
4. Deployment Using ArgoCD for Edge Devices
- Step-by-step guide on deploying anomaly detection models on edge devices using ArgoCD.
5. Introduction to Apache Kafka and S3
- Explore Apache Kafka for real-time data streaming and Amazon S3 for scalable storage solutions.
6. Viewing Kafka Messages in the Data Lake
- Learn how to view and analyze Kafka messages stored in a data lake for better insights.
7. What is Prometheus?
- Get to know Prometheus, an open-source monitoring and alerting toolkit, and its application in monitoring edge devices.
8. Monitoring Application Metrics with Prometheus
- Detailed instructions on setting up Prometheus to monitor the performance and health of your anomaly detection system.
9. What is Camel K?
- Introduction to Camel K, a lightweight integration framework built on Apache Camel, designed for Kubernetes.
10. Configuring Camel K Integrations for Data Pipelines
- Learn how to configure Camel K for seamless data pipeline integrations in your anomaly detection workflow.
11. What is a Jupyter Notebook?
- Overview of Jupyter Notebooks, an open-source web application for creating and sharing documents with live code, equations, visualizations, and narrative text.
12. Jupyter Notebooks with Code Examples
- Hands-on examples and code snippets in Jupyter Notebooks to help you implement and test anomaly detection models.
5th LF Energy Power Grid Model Meet-up SlidesDanBrown980551
5th Power Grid Model Meet-up
It is with great pleasure that we extend to you an invitation to the 5th Power Grid Model Meet-up, scheduled for 6th June 2024. This event will adopt a hybrid format, allowing participants to join us either through an online Mircosoft Teams session or in person at TU/e located at Den Dolech 2, Eindhoven, Netherlands. The meet-up will be hosted by Eindhoven University of Technology (TU/e), a research university specializing in engineering science & technology.
Power Grid Model
The global energy transition is placing new and unprecedented demands on Distribution System Operators (DSOs). Alongside upgrades to grid capacity, processes such as digitization, capacity optimization, and congestion management are becoming vital for delivering reliable services.
Power Grid Model is an open source project from Linux Foundation Energy and provides a calculation engine that is increasingly essential for DSOs. It offers a standards-based foundation enabling real-time power systems analysis, simulations of electrical power grids, and sophisticated what-if analysis. In addition, it enables in-depth studies and analysis of the electrical power grid’s behavior and performance. This comprehensive model incorporates essential factors such as power generation capacity, electrical losses, voltage levels, power flows, and system stability.
Power Grid Model is currently being applied in a wide variety of use cases, including grid planning, expansion, reliability, and congestion studies. It can also help in analyzing the impact of renewable energy integration, assessing the effects of disturbances or faults, and developing strategies for grid control and optimization.
What to expect
For the upcoming meetup we are organizing, we have an exciting lineup of activities planned:
-Insightful presentations covering two practical applications of the Power Grid Model.
-An update on the latest advancements in Power Grid -Model technology during the first and second quarters of 2024.
-An interactive brainstorming session to discuss and propose new feature requests.
-An opportunity to connect with fellow Power Grid Model enthusiasts and users.
Taking AI to the Next Level in Manufacturing.pdfssuserfac0301
Read Taking AI to the Next Level in Manufacturing to gain insights on AI adoption in the manufacturing industry, such as:
1. How quickly AI is being implemented in manufacturing.
2. Which barriers stand in the way of AI adoption.
3. How data quality and governance form the backbone of AI.
4. Organizational processes and structures that may inhibit effective AI adoption.
6. Ideas and approaches to help build your organization's AI strategy.
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsDianaGray10
Join us to learn how UiPath Apps can directly and easily interact with prebuilt connectors via Integration Service--including Salesforce, ServiceNow, Open GenAI, and more.
The best part is you can achieve this without building a custom workflow! Say goodbye to the hassle of using separate automations to call APIs. By seamlessly integrating within App Studio, you can now easily streamline your workflow, while gaining direct access to our Connector Catalog of popular applications.
We’ll discuss and demo the benefits of UiPath Apps and connectors including:
Creating a compelling user experience for any software, without the limitations of APIs.
Accelerating the app creation process, saving time and effort
Enjoying high-performance CRUD (create, read, update, delete) operations, for
seamless data management.
Speakers:
Russell Alfeche, Technology Leader, RPA at qBotic and UiPath MVP
Charlie Greenberg, host
In the realm of cybersecurity, offensive security practices act as a critical shield. By simulating real-world attacks in a controlled environment, these techniques expose vulnerabilities before malicious actors can exploit them. This proactive approach allows manufacturers to identify and fix weaknesses, significantly enhancing system security.
This presentation delves into the development of a system designed to mimic Galileo's Open Service signal using software-defined radio (SDR) technology. We'll begin with a foundational overview of both Global Navigation Satellite Systems (GNSS) and the intricacies of digital signal processing.
The presentation culminates in a live demonstration. We'll showcase the manipulation of Galileo's Open Service pilot signal, simulating an attack on various software and hardware systems. This practical demonstration serves to highlight the potential consequences of unaddressed vulnerabilities, emphasizing the importance of offensive security practices in safeguarding critical infrastructure.
What is an RPA CoE? Session 1 – CoE VisionDianaGray10
In the first session, we will review the organization's vision and how this has an impact on the COE Structure.
Topics covered:
• The role of a steering committee
• How do the organization’s priorities determine CoE Structure?
Speaker:
Chris Bolin, Senior Intelligent Automation Architect Anika Systems
"Scaling RAG Applications to serve millions of users", Kevin GoedeckeFwdays
How we managed to grow and scale a RAG application from zero to thousands of users in 7 months. Lessons from technical challenges around managing high load for LLMs, RAGs and Vector databases.
AppSec PNW: Android and iOS Application Security with MobSFAjin Abraham
Mobile Security Framework - MobSF is a free and open source automated mobile application security testing environment designed to help security engineers, researchers, developers, and penetration testers to identify security vulnerabilities, malicious behaviours and privacy concerns in mobile applications using static and dynamic analysis. It supports all the popular mobile application binaries and source code formats built for Android and iOS devices. In addition to automated security assessment, it also offers an interactive testing environment to build and execute scenario based test/fuzz cases against the application.
This talk covers:
Using MobSF for static analysis of mobile applications.
Interactive dynamic security assessment of Android and iOS applications.
Solving Mobile app CTF challenges.
Reverse engineering and runtime analysis of Mobile malware.
How to shift left and integrate MobSF/mobsfscan SAST and DAST in your build pipeline.
Conversational agents, or chatbots, are increasingly used to access all sorts of services using natural language. While open-domain chatbots - like ChatGPT - can converse on any topic, task-oriented chatbots - the focus of this paper - are designed for specific tasks, like booking a flight, obtaining customer support, or setting an appointment. Like any other software, task-oriented chatbots need to be properly tested, usually by defining and executing test scenarios (i.e., sequences of user-chatbot interactions). However, there is currently a lack of methods to quantify the completeness and strength of such test scenarios, which can lead to low-quality tests, and hence to buggy chatbots.
To fill this gap, we propose adapting mutation testing (MuT) for task-oriented chatbots. To this end, we introduce a set of mutation operators that emulate faults in chatbot designs, an architecture that enables MuT on chatbots built using heterogeneous technologies, and a practical realisation as an Eclipse plugin. Moreover, we evaluate the applicability, effectiveness and efficiency of our approach on open-source chatbots, with promising results.
3. Static Name Resolution
module module
def import def def defA
A
B
6 y funf
x +
x y
x +
3 s
5s
module A {
def s = 5
}
module B {
import A
def x = 6
def y = 3 + s
def f =
fun x { x + y }
}
4. Static Name Resolution
module module
def import def def defA
A
B
6 y funf
x +
x y
x +
3 s
5s
module A {
def s = 5
}
module B {
import A
def x = 6
def y = 3 + s
def f =
fun x { x + y }
}
5. Static Name Resolution
module module
def import def def defA
A
B
6 y funf
x +
x y
x +
3 s
5s
module A {
def s = 5
}
module B {
import A
def x = 6
def y = 3 + s
def f =
fun x { x + y }
}
6. Static Name Resolution
module module
def import def def defA
A
B
6 y funf
x +
x y
x +
3 s
5s
module A {
def s = 5
}
module B {
import A
def x = 6
def y = 3 + s
def f =
fun x { x + y }
}
7. Static Name Resolution
module module
def import def def defA
A
B
6 y funf
x +
x y
x +
3 s
5s
module A {
def s = 5
}
module B {
import A
def x = 6
def y = 3 + s
def f =
fun x { x + y }
}
8. Based On …
• Declarative Name Binding and Scope Rules
- NaBL name binding language
- Gabriël D. P. Konat, Lennart C. L. Kats, Guido Wachsmuth, Eelco Visser
- SLE 2012
• A Language Designer's Workbench
- A one-stop-shop for implementation and verification of language designs
- Eelco Visser, Guido Wachsmuth, Andrew P. Tolmach, Pierre Neron, Vlad A. Vergu,
Augusto Passalaqua, Gabriël D. P. Konat
- Onward 2014
• A Theory of Name Resolution
- Pierre Néron, Andrew Tolmach, Eelco Visser, Guido Wachsmuth
- ESOP 2015
• A Constraint Language for Static Semantic Analysis based on Scope
Graphs
- Hendrik van Antwerpen, Pierre Neron, Andrew P. Tolmach, Eelco Visser, Guido
Wachsmuth
- PEPM 2016
9. Detour:
Declare Your Syntax
(an analogy for formalizing declarative name binding)
Pure and declarative syntax definition: paradise lost and regained
Lennart C. L. Kats, Eelco Visser, Guido Wachsmuth
Onward 2010
10. Language = Set of Sentences
fun (x : Int) { x + 1 }
Text is a convenient interface for writing and reading programs
11. Language = Set of Trees
Fun
AddArgDecl
VarRefId Int
“1”
VarDeclId
“x”
TXINT
“x”
Tree is a convenient interface for transforming programs
12. Tree Transformation
Tree is a convenient interface for transforming programs
Semantic
transform
translate
eval
analyze
refactor
type check
Syntactic
coloring
outline view
completion
13. Language = Sentences and Trees
parse
format
different representations convenient for different purposes
14. SDF3 defines Trees and Sentences
parse(s) = t where format(t) == s (modulo layout)
Expr.Int = INT
Expr.Add = <<Expr> + <Expr>>
Expr.Mul = <<Expr> * <Expr>>
trees
(structure)
parse
(text to tree)
format
(tree to text)
+ =>
19. Priority and Associativity
context-free syntax
Expr.Int = INT
Expr.Add = <<Expr> + <Expr>> {left}
Expr.Mul = <<Expr> * <Expr>> {left}
context-free priorities
Expr.Mul > Expr.Add
Recent improvement: safe disambiguation of operator precedence
Afroozeh et al. (SLE 2013, Onward 2015)
Add
VarRef VarRef
“y”“x”
Mul
Int
“3”
Add
VarRef
VarRef
“y”
“x”
Mul
Int
“3”
3 * x + y
20. Declarative Syntax Definition
• Representation: (Abstract Syntax) Trees
- Standardized representation for structure of programs
- Basis for syntactic and semantic operations
• Formalism: Syntax Definition
- Productions + Constructors + Templates + Disambiguation
- Language-specific rules: structure of each language construct
• Language-Independent Interpretation
- Well-formedness of abstract syntax trees
‣ provides declarative correctness criterion for parsing
- Parsing algorithm
‣ No need to understand parsing algorithm
‣ Debugging in terms of representation
- Formatting based on layout hints in grammar
21. Declare Your Names
A Theory of Name Resolution
Pierre Néron, Andrew Tolmach, Eelco Visser, Guido Wachsmuth
ESOP 2015
22. Language = Set of Trees
Fun
AddArgDecl
VarRefId Int
“1”
VarDeclId
“x”
TXINT
“x”
Tree is a convenient interface for transforming programs
23. Language = Set of Graphs
Fun
AddArgDecl
VarRefId Int
“1”
VarDeclId TXINT
Edges from references to declarations
25. Name Resolution is Pervasive
• Used in many different language artifacts
- compiler
- interpreter
- semantics
- IDE
- refactoring
• Binding rules encoded in many different and ad-hoc ways
- symbol tables
- environments
- substitutions
• No standard approach to formalization
- there is no BNF for name binding
• No reuse of binding rules between artifacts
- how do we know substitution respects binding rules?
26. NaBL Name Binding Language
binding rules // variables
Param(t, x) :
defines Variable x of type t
Let(bs, e) :
scopes Variable
Bind(t, x, e) :
defines Variable x of type t
Var(x) :
refers to Variable x
Declarative Name Binding and Scope Rules
Gabriël D. P. Konat, Lennart C. L. Kats, Guido Wachsmuth, Eelco Visser
SLE 2012
Declarative specification
Abstracts from implementation
Incremental name resolution
But:
How to explain it to Coq?
What is the semantics of NaBL?
27. NaBL Name Binding Language
Declarative Name Binding and Scope Rules
Gabriël D. P. Konat, Lennart C. L. Kats, Guido Wachsmuth, Eelco Visser
SLE 2012
Especially:
What is the semantics of imports?
binding rules // classes
Class(c, _, _, _) :
defines Class c of type ClassT(c)
scopes Field, Method, Variable
Extends(c) :
imports Field, Method from Class c
ClassT(c) :
refers to Class c
New(c) :
refers to Class c
28. A Theory of Name Resolution
• Representation: Scope Graphs
- Standardized representation for lexical scoping structure of programs
- Path in scope graph relates reference to declaration
- Basis for syntactic and semantic operations
- Supports ambiguous / erroneous programs
• Formalism: Name Binding Specification
- References + Declarations + Scopes + Reachability + Visibility
- Language-specific rules: mapping constructs to scope graph
• Language-Independent Interpretation
- Resolution calculus
‣ Correctness of path with respect to scope graph
‣ Separation of reachability and visibility (disambiguation)
- Name resolution algorithm
‣ sound wrt calculus
- Transformation
‣ Alpha equivalence, substitution, refactoring, …
31. A Calculus for Name Resolution
S R1 R2 SR
SRS
I(R1)
S’S
S’S P
Sx
Sx R
xS
xS D
Path in scope graph connects reference to declaration
Scopes, References, Declarations, Parents, Imports
75. Qualified Names
module N1 {
def s1 = 5
}
module M1 {
def x1 = 1 + N2.s2
}
S0
N1
SN
s2
S0
N2
R
D
R
I(N2) D
X1
s1
76. A Calculus for Name Resolution
S R1 R2 SR
SRS
I(R1)
S’S
S’S P
Sx
Sx R
xS
xS D
Reachability of declarations from references
through scope graph edges
How about ambiguities?
References with multiple paths
78. A Calculus for Name Resolution
S R1 R2 SR
SRS
I(R1)
S’S
S’S P
Sx
Sx R
xS
xS D
I(_).p’ < P.p
D < I(_).p’
D < P.p
s.p < s.p’
p < p’
Reachability
VisibilityWell formed path: R.P*.I(_)*.D
90. Shadowing
S0
S1
S2
def x3 = z2 5 7
def z1 =
fun x1 {
fun y1 {
x2 + y2
}
}
S1
S2
x1
y1
y2 x2
z1
x3S0z2
R
P
P
D
91. Shadowing
S0
S1
S2
def x3 = z2 5 7
def z1 =
fun x1 {
fun y1 {
x2 + y2
}
}
S1
S2
x1
y1
y2 x2
z1
x3S0z2
D
P
R
R
P
P
D
92. Shadowing
S0
S1
S2
D < P.p
def x3 = z2 5 7
def z1 =
fun x1 {
fun y1 {
x2 + y2
}
}
S1
S2
x1
y1
y2 x2
z1
x3S0z2
D
P
R
R
P
P
D
93. Shadowing
S0
S1
S2
D < P.p
s.p < s.p’
p < p’
def x3 = z2 5 7
def z1 =
fun x1 {
fun y1 {
x2 + y2
}
}
S1
S2
x1
y1
y2 x2
z1
x3S0z2
D
P
R
R
P
P
D
94. Shadowing
S0
S1
S2
D < P.p
s.p < s.p’
p < p’
def x3 = z2 5 7
def z1 =
fun x1 {
fun y1 {
x2 + y2
}
}
S1
S2
x1
y1
y2 x2
z1
x3S0z2
D
P
R
R
P
P
D
R.P.D < R.P.P.D
103. Imports vs. Includes
S0def z3 = 2
module A1 {
def z1 = 5
}
import A2
def x1 = 1 + z2
SA A1
SA
z1
z2
S0
A2
x1z3
104. Imports vs. Includes
S0def z3 = 2
module A1 {
def z1 = 5
}
import A2
def x1 = 1 + z2
SA A1
SA
z1
z2
S0
A2
x1
R
z3
D
105. Imports vs. Includes
S0def z3 = 2
module A1 {
def z1 = 5
}
import A2
def x1 = 1 + z2
SA A1
SA
z1
z2
S0
A2
x1
I(A2
)
R
D
z3
R
D
106. Imports vs. Includes
S0def z3 = 2
module A1 {
def z1 = 5
}
import A2
def x1 = 1 + z2
SA A1
SA
z1
z2
S0
A2
x1
I(A2
)
R
D
z3
R
D
D < I(_).p’
107. Imports vs. Includes
S0def z3 = 2
module A1 {
def z1 = 5
}
import A2
def x1 = 1 + z2
SA A1
SA
z1
z2
S0
A2
x1
I(A2
)
R
D
z3
R
D
D < I(_).p’
R.D < R.I(A2).D
122. Transitive vs. Non-Transitive
With transitive imports, a well formed path is R.P*.I(_)*.D
With non-transitive imports, a well formed path is R.P*.I(_)?
.D
A1
SA
z1
B1
SB
S0
A2
I(A2
)
D
C1
SCz2
I(B2
)
R
x1 B2
??
module A1 {
def z1 = 5
}
module B1 {
import A2
}
module C1 {
import B2
def x1 = 1 + z2
}
SA
SB
SC
123. A Calculus for Name Resolution
S R1 R2 SR
SRS
I(R1)
S’S
S’S P
Sx
Sx R
xS
xS D
I(_).p’ < P.p
D < I(_).p’
D < P.p
s.p < s.p’
p < p’
Reachability
VisibilityWell formed path: R.P*.I(_)*.D
130. C# Namespaces and Partial Classes
namespace N1 {
using M2;
partial class C3 {
int f4;
}
}
namespace N5 {
partial class C6 {
int m7() {
return f8;
}
}
}
1
3 6
4 7
8
C3 C6
N1 N5
f4 m7
N1 N5
C3 C6
f8
2 M2 5
131. More Examples?
Here the audience proposes binding patterns that they
think are not covered by the scope graph framework
(and they may be right?)
132. Blocks in Java
class Foo {
void foo() {
int x = 1;
{
int y = 2;
}
x = y;
}
}
What is the scope graph for this program?
Is the y declaration visible to the y reference?
135. Name Binding Constraints
false // always fails
true // always succeeds
C1, C2 // conjunction of constraints
[[ e ^ (s) ]] // generate constraints for sub-term
new s // generate a new scope
NS{x} <- s // declaration of name x in namespace NS in scope s
NS{x} -> s // reference of name x in namespace NS in scope s
s -> s' // unlabeled scope edge from s to s'
s -L-> s' // scope edge from s to s' labeled L
NS{x} |-> d // resolve reference x in namespace NS to declaration d
C | error $[something is wrong] // custom error message
C | warning $[does not look right] // custom warning
137. Let Bindings
let
var x : int := 5
var f : int := 1
in
for y := 1 to x do (
f := f * y
)
end
let function fact(n : int) : int =
if n < 1 then 1 else (n * fact(n - 1))
in fact(10)
end
138. Let Bindings are Sequential
let
var x : int := 0 + z // z not in scope
var y : int := x + 1
var z : int := x + y + 1
in
x + y + z
end
139. Adjacent Function Declarations are Mutually Recursive
let
function odd(x : int) : int =
if x > 0 then even(x - 1) else false
function even(x : int) : int =
if x > 0 then odd(x - 1) else true
in
even(34)
end
let
function odd(x : int) : int =
if x > 0 then even(x - 1) else false
var x : int
function even(x : int) : int =
if x > 0 then odd(x - 1) else true
in
even(34)
end
140. Namespaces
let
type foo = int
function foo(x : foo) : foo = 3
var foo : foo := foo(4)
in foo(56) + foo // both refer to the variable foo
end
142. Set Up
module static-semantics
imports signatures/-
imports nabl-lib
signature
name resolution
labels
D, P, I
well-formedness
P* . I*
order
D < P,
D < I,
I < P
rules
init ^ (s) :=
new s, // generate the root scope
Type{"int"} <- s. // declare primitive type int
143. Library
module nabl-lib
rules // auxiliary
[[ None() ^ (s) ]] := true.
[[ Some(e) ^ (s) ]] := [[ e ^ (s) ]].
Map[[ [] ^ (s) ]] := true.
Map[[ [ x | xs ] ^ (s) ]] :=
[[ x ^ (s) ]], Map[[ xs ^ (s) ]].
Map2[[ [] ^ (s, s') ]] := true.
Map2[[ [ x | xs ] ^ (s, s') ]] :=
[[ x ^ (s, s') ]], Map2[[ xs ^ (s, s') ]].
144. Variable Declarations and References
rules // variable declarations
[[ VarDec(x, t, e) ^ (s, s_outer) ]] :=
Var{x} <- s,
[[ t ^ (s_outer) ]],
[[ e ^ (s_outer) ]].
[[ VarDecNoInit(x, t) ^ (s, s_outer) ]] :=
Var{x} <- s,
[[ t ^ (s_outer) ]].
rules // variable references
[[ Var(x) ^ (s) ]] :=
Var{x} -> s, // declare x as variable reference
Var{x} |-> d. // check that x resolves to a declaration
let
var x : int := 5
var f : int := 1
in
for y := 1 to x do (
f := f * y
)
end
145. For Binds Loop Index Variable
let
var x : int := 5
var f : int := 1
in
for y := 1 to x do (
f := f * y
)
end
rules // binding statements
[[ For(Var(x), e1, e2, e3) ^ (s) ]] :=
new s',
s' -P-> s,
Var{x} <- s',
[[ e1 ^ (s) ]], // x not bound in loop bounds
[[ e2 ^ (s) ]],
[[ e3 ^ (s') ]]. // x bound in body
146. Function Declarations and References
rules // function declarations
[[ FunDecs(fdecs) ^ (s, s_outer) ]] :=
Map2[[ fdecs ^ (s, s_outer) ]].
[[ FunDec(f, args, t, e) ^ (s, s_outer) ]] :=
Var{f} <- s, // declare f
new s', // declare a new scope for body of function
s' -P-> s, // make lexical environment accessible in body
Map2[[ args ^ (s', s_outer) ]],
[[ t ^ (s_outer) ]],
[[ e ^ (s') ]].
[[ FArg(x, t) ^ (s, s_outer) ]] :=
Var{x} <- s, // declare argument x as a variable declaration
[[ t ^ (s_outer) ]].
rules // function calls
[[ Call(Var(f), exps) ^ (s) ]] :=
Var{f} -> s, // declare f as a function reference
Var{f} |-> d | error $[Function [f] not declared],
// check that f resolves to a declaration
Map[[ exps ^ (s) ]].
let function fact(n : int) : int =
if n < 1 then 1 else (n * fact(n - 1))
in fact(10)
end
147. Let Bindings are Sequential
rules // declarations
[[ Let(blocks, exps) ^ (s) ]] :=
new s', // declare a new scope for the names introduced by the let
s' -P-> s, // declare s as its parent scope
new s_body, // scope for body of the let
Decs[[ blocks ^ (s', s_body) ]],
Map[[ exps ^ (s_body) ]].
Decs[[ [] ^ (s, s_body) ]] :=
s_body -P-> s.
Decs[[ [block | blocks] ^ (s_outer, s_body) ]] :=
new s', s' -P-> s_outer,
[[ block ^ (s', s_outer) ]],
Decs[[ blocks ^ (s', s_body) ]].
let
var x : int := 0 + z // z not in scope
var y : int := x + 1
var z : int := x + y + 1
in
x + y + z
end
148. Adjacent Function Declarations are Mutually Recursive
let
function odd(x : int) : int =
if x > 0 then even(x - 1) else false
function even(x : int) : int =
if x > 0 then odd(x - 1) else true
in
even(34)
end
let
function odd(x : int) : int =
if x > 0 then even(x - 1) else false
var x : int
function even(x : int) : int =
if x > 0 then odd(x - 1) else true
in
even(34)
end
149. Namespaces
let
type foo = int
function foo(x : foo) : foo = 3
var foo : foo := foo(4)
in foo(56) + foo // both refer to the variable foo
end
rules // type declarations
[[ TypeDecs(tdecs) ^ (s, s_outer) ]] :=
Map2[[ tdecs ^ (s, s_outer) ]].
[[ TypeDec(x, t) ^ (s, s_outer) ]] :=
Type{x} <- s,
[[ t ^ (s_outer) ]].
rules // types
[[ Tid(x) ^ (s) ]] :=
Type{x} -> s,
Type{x} |-> d | error $[Type [x] not declared].
152. Issues with the Reachability Calculus
S R1 R2 SR
SRS
I(R1)
S’S
S’S P
Sx
Sx R
xS
xS D
I(_).p’ < P.p
D < I(_).p’
D < P.p
s.p < s.p’
p < p’
Well formed path: R.P*.I(_)*.D
Disambiguating import paths
Fixed visibility policy
Cyclic Import Paths
Multi-import interpretation
153. Resolution Calculus with Edge Labels
s the resolution relation for graph G.
collection JNKG is the multiset defined
DG(S)), JR(S)KG = ⇡(RG(S)), and
`G p : S 7 ! xD
i }) where ⇡(A) is
ojecting the identifiers from a set A of
iven a multiset M, 1M (x) denotes the
nes the resolution of a reference to a
as a most specific, well-formed path
n through a sequence of edges. A path
ng the atomic scope transitions in the
of steps:
l, S2) is a direct transition from the
pe S2. This step records the label of
s used.
, yR
, S) requires the resolution of ref-
n with associated scope S to allow a
rrent scope and scope S.
nds with a declaration step D(xD
) that
path is leading to.
ion in the graph from reference xR
i
`G p : xR
i 7 ! xD
i according to
. These rules all implicitly apply to
omit to avoid clutter. The calculus
n in terms of edges in the scope graph,
isible declarations. Here I is the set of
vice needed to avoid “out of thin air”
Well-formed paths
WF(p) , labels(p) 2 E
Visibility ordering on paths
label(s1) < label(s2)
s1 · p1 < s2 · p2
p1 < p2
s · p1 < s · p2
Edges in scope graph
S1
l
S2
I ` E(l, S2) : S1 ! S2
(E)
S1
l
yR
i yR
i /2 I I ` p : yR
i 7 ! yD
j yD
j S2
I ` N(l, yR
i , S2) : S1 ! S2
(N)
Transitive closure
I, S ` [] : A ⇣ A
(I)
B /2 S I ` s : A ! B I, {B} [ S ` p : B ⇣ C
I, S ` s · p : A ⇣ C
(T)
Reachable declarations
I, {S} ` p : S ⇣ S0
WF(p) S0
xD
i
I ` p · D(xD
i ) : S ⇢ xD
i
(R)
Visible declarations
I ` p : S ⇢ xD
i
8j, p0
(I ` p0
: S ⇢ xD
j ) ¬(p0
< p))
I ` p : S 7 ! xD
i
(V )
Reference resolution
xR
i S {xR
i } [ I ` p : S 7 ! xD
j
I ` p : xR
i 7 ! xD
j
(X)
G, |= !N
JN1KG ✓ JN2KG
G, |= N1
⇢
⇠ N2
(C-SUBNAME)
t1 = t2
G, |= t1 ⌘ t2
(C-EQ)
Figure 8. Interpretation of resolution and typing constraints
Resolution paths
s := D(xD
i ) | E(l, S) | N(l, xR
i , S)
p := [] | s | p · p (inductively generated)
[] · p = p · [] = p
(p1 · p2) · p3 = p1 · (p2 · p3)
Well-formed paths
WF(p) , labels(p) 2 E
Visibility ordering on paths
label(s1) < label(s2)
s1 · p1 < s2 · p2
p1 < p2
s · p1 < s · p2
Edges in scope graph
S1
l
S2
I ` E(l, S2) : S1 ! S2
(E)
S1
l
yR
i yR
i /2 I I ` p : yR
i 7 ! yD
j yD
j S2
I ` N(l, yR
i , S2) : S1 ! S2
(N)
Transitive closure
I, S ` [] : A ⇣ A
(I)
B /2 S I ` s : A ! B I, {B} [ S ` p : B ⇣ C
I, S ` s · p : A ⇣ C
(T)
Reachable declarations
I, {S} ` p : S ⇣ S0
WF(p) S0
xD
i
I ` p · D(xD
i ) : S ⇢ xD
i
(R)
Visible declarations
I ` p : S ⇢ xD
i
8j, p0
(I ` p0
: S ⇢ xD
j ) ¬(p0
< p))
I ` p : S 7 ! xD
i
(V )
Reference resolution
xR
S {xR
} [ I ` p : S 7 ! xD
C := CG
| CTy | CRes | C ^ C | True
CG
:= R S | S D | S l
S | D S | S l
R
CRes := R 7! D | D S | !N | N ⇢
⇠ N
CTy := T ⌘ T | D : T
D := | xD
i
R := xR
i
S := & | n
T := ⌧ | c(T, ..., T) with c 2 CT
N := D(S) | R(S) | V(S)
Figure 7. Syntax of constraints
scope graph resolution calculus (described in Section 3.3). Finally,
we apply |= with G set to CG
.
To lift this approach to constraints with variables, we simply
apply a multi-sorted substitution , mapping type variables ⌧ to
ground types, declaration variables to ground declarations and
scope variables & to ground scopes. Thus, our overall definition of
satisfaction for a program p is:
(CG
), |= (CRes
) ^ (CTy
) (⇧)
154. Visibility Policies
Lexical scope
L := {P} E := P⇤
D < P
Non-transitive imports
L := {P, I} E := P⇤
· I?
D < P, D < I, I < P
Transitive imports
L := {P, TI} E := P⇤
· TI⇤
D < P, D < TI, TI < P
Transitive Includes
L := {P, Inc} E := P⇤
· Inc⇤
D < P, Inc < P
Transitive includes and imports, and non-transitive imports
L := {P, Inc, TI, I} E := P⇤
· (Inc | TI)⇤
· I?
D < P, D < TI, TI < P, Inc < P, D < I, I < P,
Figure 10. Example reachability and visibility policies by instan-
tiation of path well-formedness and visibility.
3.4 Parameterization
R
Envre [
EnvL
re [
EnvD
re [
Envl
re [
I
155. Seen Imports
hout import tracking.
ficity order on paths is
e visibility policies can
e and specificity order.
module A1 {
module A2 {
def a3 = ...
}
}
import A4
def b5 = a6
Fig. 11. Self im-
port
tion
the
dule
far,
few
!
t A4
ody
?
13
AD
2 :SA2 2 D(SA1 )
AR
4 2 I(Sroot)
AR
4 2 R(Sroot) AD
1 :SA1 2 D(Sroot)
AR
4 7 ! AD
1 :SA1
Sroot ! SA1 (⇤)
Sroot ⇢ AD
2 :SA2
AR
4 2 R(Sroot) Sroot 7 ! AD
2 :SA2
AR
4 7 ! AD
2 :SA2
Fig. 10. Derivation for AR
4 7 ! AD
2 :SA2 in a calculus without import tracking.
The complete definition of well-formed paths and specificity order on paths is
given in Fig. 2. In Section 2.5 we discuss how alternative visibility policies can
be defined by just changing the well-formedness predicate and specificity order.
module A1 {
module A2 {
def a3 = ...
}
}
import A4
def b5 = a6
Seen imports. Consider the example in Fig. 11. Is declaration
a3 reachable in the scope of reference a6? This reduces to the
question whether the import of A4 can resolve to module
A2. Surprisingly, it can, in the calculus as discussed so far,
as shown by the derivation in Fig. 10 (which takes a few
shortcuts). The conclusion of the derivation is that AR
4 7 !
AD
:S . This conclusion is obtained by using the import at A
as shown by the derivation in Fig. 10 (which takes
shortcuts). The conclusion of the derivation is that AR
4
AD
2 :SA2 . This conclusion is obtained by using the import
to conclude at step (*) that Sroot ! SA1
, i.e. that the
of module A1 is reachable! In other words, the import
is used in its own resolution. Intuitively, this is nonsen
To rule out this kind of behavior we extend the cal
to keep track of the set of seen imports I using judgem
of the form I ` p : xR
i 7 ! xD
j . We need to extend all ru
pass the set I, but only the rules for resolution and im
are truly affected:
xR
i 2 R(S) {xR
i } [ I ` p : S 7 ! xD
j
I ` p : xR
i 7 ! xD
j
yR
i 2 I(S1) I I ` p : yR
i 7 ! yD
j :S2
I ` I(yR
i , yD
j :S2) : S1 ! S2
With this final ingredient, we reach the full calcul
156. 4
def b5 = a6
Fig. 11. Self im-
port
module A1 {
module B2 {
def x3 = 1
}
}
module B4 {
module A5 {
def y6 = 2
}
}
module C7 {
import A8
import B9
def z10 = x11
+ y12
}
Fig. 12. Anoma-
lous resolution
. The conclusion of the derivation is that AR
4 7 !
This conclusion is obtained by using the import at A4
de at step (*) that Sroot ! SA1
, i.e. that the body
A1 is reachable! In other words, the import of A4
its own resolution. Intuitively, this is nonsensical.
e out this kind of behavior we extend the calculus
ack of the set of seen imports I using judgements
m I ` p : xR
i 7 ! xD
j . We need to extend all rules to
et I, but only the rules for resolution and import
affected:
xR
i 2 R(S) {xR
i } [ I ` p : S 7 ! xD
j
I ` p : xR
i 7 ! xD
j
(X)
yR
i 2 I(S1) I I ` p : yR
i 7 ! yD
j :S2
I ` I(yR
i , yD
j :S2) : S1 ! S2
(I)
this final ingredient, we reach the full calculus in
is not hard to see that the resolution relation is
ded. The only recursive invocation (via the I rule)
ictly larger set I of seen imports (via the X rule); since the set R(G)
Anomaly
4
def b5 = a6
Fig. 11. Self im-
port
module A1 {
module B2 {
def x3 = 1
}
}
module B4 {
module A5 {
def y6 = 2
}
}
module C7 {
import A8
import B9
def z10 = x11
+ y12
}
Fig. 12. Anoma-
lous resolution
R
4 7 !
at A4
body
of A4
sical.
culus
ments
les to
mport
(X)
(I)
us in
on is
rule)
rule); since the set R(G)
2
1
3
1
3
2
157. Resolution Algorithm
< P
P,
nstan-
R[I](xR
) := let (r, s) = EnvE [{xR
} [ I, ;](Sc(xR
))} in
(
U if r = P and {xD
|xD
2 s} = ;
{xD
|xD
2 s}
Envre [I, S](S) :=
(
(T, ;) if S 2 S or re = ?
Env
L[{D}
re [I, S](S)
EnvL
re [I, S](S) :=
[
l2Max(L)
⇣
Env
{l0
2L|l0
<l}
re [I, S](S) Envl
re [I, S](S)
⌘
EnvD
re [I, S](S) :=
(
(T, ;) if [] /2 re
(T, D(S))
Envl
re [I, S](S) :=
8
><
>:
(P, ;) if S
I
l contains a variable or ISl[I](S) = U
S
S02
⇣
ISl[I](S)[S
I
l
⌘
Env(l 1re)[I, {S} [ S](S0)
ISl
[I](S) :=
(
U if 9yR
2 (S
B
l I) s.t. R[I](yR
) = U
{S0 | yR
2 (S
B
l I) ^ yD
2 R[I](yR
) ^ yD
S0}
159. Language-independent 𝜶-equivalence
Program similarity
Equivalence
define ↵-equivalence using scope graphs. Except for the leaves rep
ifiers, two ↵-equivalent programs must have the same abstract
write P ' P’ (pronounced “P and P’ are similar”) when the AS
re equal up to identifiers. To compare two programs we first c
T structures; if these are equal then we compare how identifiers
programs. Since two potentially ↵-equivalent programs are simi
s occur at the same positions. In order to compare the identifiers’
efine equivalence classes of positions of identifiers in a program: p
me equivalence class are declarations of or reference to the same
ract position ¯x identifies the equivalence class corresponding to
x.
n a program P, we write P for the set of positions correspon
s and declarations and PX for P extended with the artificial p
We define the
P
⇠ equivalence relation between elements of PX
if have same AST ignoring identifier names
160. Language-independent 𝜶-equivalence
Position equivalence
e same equivalence class are declarations of or reference to the same enti
abstract position ¯x identifies the equivalence class corresponding to the fr
ble x.
Given a program P, we write P for the set of positions corresponding
ences and declarations and PX for P extended with the artificial positio
¯x). We define the
P
⇠ equivalence relation between elements of PX as t
xive symmetric and transitive closure of the resolution relation.
nition 7 (Position equivalence).
` p : r i
x 7 ! di0
x
i
P
⇠ i0
i0 P
⇠ i
i
P
⇠ i0
i
P
⇠ i0
i0 P
⇠ i00
i
P
⇠ i00
i
P
⇠ i
his equivalence relation, the class containing the abstract free variable d
ion can not contain any other declaration. So the references in a particu
are either all free or all bound.
mma 6 (Free variable class). The equivalence class of a free variable do
contain any other declaration, i.e. 8 di
x s.t. i
P
⇠ ¯x =) i = ¯x
xi xi'
Program similarity
Equivalence
define ↵-equivalence using scope graphs. Except for the leaves rep
ifiers, two ↵-equivalent programs must have the same abstract
write P ' P’ (pronounced “P and P’ are similar”) when the AS
re equal up to identifiers. To compare two programs we first c
T structures; if these are equal then we compare how identifiers
programs. Since two potentially ↵-equivalent programs are simi
s occur at the same positions. In order to compare the identifiers’
efine equivalence classes of positions of identifiers in a program: p
me equivalence class are declarations of or reference to the same
ract position ¯x identifies the equivalence class corresponding to
x.
n a program P, we write P for the set of positions correspon
s and declarations and PX for P extended with the artificial p
We define the
P
⇠ equivalence relation between elements of PX
if have same AST ignoring identifier names
161. Language-independent 𝜶-equivalence
Position equivalence
e same equivalence class are declarations of or reference to the same enti
abstract position ¯x identifies the equivalence class corresponding to the fr
ble x.
Given a program P, we write P for the set of positions corresponding
ences and declarations and PX for P extended with the artificial positio
¯x). We define the
P
⇠ equivalence relation between elements of PX as t
xive symmetric and transitive closure of the resolution relation.
nition 7 (Position equivalence).
` p : r i
x 7 ! di0
x
i
P
⇠ i0
i0 P
⇠ i
i
P
⇠ i0
i
P
⇠ i0
i0 P
⇠ i00
i
P
⇠ i00
i
P
⇠ i
his equivalence relation, the class containing the abstract free variable d
ion can not contain any other declaration. So the references in a particu
are either all free or all bound.
mma 6 (Free variable class). The equivalence class of a free variable do
contain any other declaration, i.e. 8 di
x s.t. i
P
⇠ ¯x =) i = ¯x
xi xi'
Program similarity
Equivalence
define ↵-equivalence using scope graphs. Except for the leaves rep
ifiers, two ↵-equivalent programs must have the same abstract
write P ' P’ (pronounced “P and P’ are similar”) when the AS
re equal up to identifiers. To compare two programs we first c
T structures; if these are equal then we compare how identifiers
programs. Since two potentially ↵-equivalent programs are simi
s occur at the same positions. In order to compare the identifiers’
efine equivalence classes of positions of identifiers in a program: p
me equivalence class are declarations of or reference to the same
ract position ¯x identifies the equivalence class corresponding to
x.
n a program P, we write P for the set of positions correspon
s and declarations and PX for P extended with the artificial p
We define the
P
⇠ equivalence relation between elements of PX
if have same AST ignoring identifier names
ed proof is in appendix A.5, we first prove:
r i
x 7 ! d ¯x
x ) =) 8 p di0
x , p ` r i
x 7 ! di0
x =) i0
= ¯x ^ p =
eed by induction on the equivalence relation.
ce classes defined by this relation contain references to
me entity. Given this relation, we can state that two p
f the identifiers at identical positions refer to the same e
he same equivalence class:
(↵-equivalence). Two programs P1 and P2 are ↵-equi
2) when they are similar and have the same ⇠-equivalen
P1
↵
⇡ P2 , P1 ' P2 ^ 8 e e0
, e
P1
⇠ e0
, e
P2
⇠ e0
is an equivalence relation since ' and , are equivalenc(with some further details about free variables)
Alpha equivalence
162. Preserving ambiguity
25
module A1 {
def x2 := 1
}
module B3 {
def x4 := 2
}
module C5 {
import A6 B7 ;
def y8 := x9
}
module D10 {
import A11 ;
def y12 := x13
}
module E14 {
import B15 ;
def y16 := x17
}
P1
module AA1 {
def z2 := 1
}
module BB3 {
def z4 := 2
}
module C5 {
import AA6 BB7 ;
def s8 := z9
}
module D10 {
import AA11 ;
def u12 := z13
}
module E14 {
import BB15 ;
def v16 := z17
}
P2
module A1 {
def z2 := 1
}
module B3 {
def x4 := 2
}
module C5 {
import A6 B7 ;
def y8 := z9
}
module D10 {
import A11 ;
def y12 := z13
}
module E14 {
import B15 ;
def y16 := x17
}
P3
Fig. 23. ↵-equivalence and duplicate declarationP1
Lemma 6 (Free variable class). The equivalence class of a fr
ot contain any other declaration, i.e. 8 di
x s.t. i
P
⇠ ¯x =) i = ¯x
Proof. Detailed proof is in appendix A.5, we first prove:
8 r i
x, (` > : r i
x 7 ! d ¯x
x ) =) 8 p di0
x , p ` r i
x 7 ! di0
x =) i0
= ¯x
nd then proceed by induction on the equivalence relation.
The equivalence classes defined by this relation contain reference
ions of the same entity. Given this relation, we can state that t
↵-equivalent if the identifiers at identical positions refer to the s
s belong to the same equivalence class:
Definition 8 (↵-equivalence). Two programs P1 and P2 are ↵
oted P1
↵
⇡ P2) when they are similar and have the same ⇠-equi
P1
↵
⇡ P2 , P1 ' P2 ^ 8 e e0
, e
P1
⇠ e0
, e
P2
⇠ e0P2 P2
Lemma 6 (Free variable class). The e
not contain any other declaration, i.e. 8 d
Proof. Detailed proof is in appendix A.5,
8 r i
x, (` > : r i
x 7 ! d ¯x
x ) =) 8 p di0
x , p `
and then proceed by induction on the equ
The equivalence classes defined by this rel
tions of the same entity. Given this relatio
↵-equivalent if the identifiers at identical
is belong to the same equivalence class:
Definition 8 (↵-equivalence). Two pro
noted P1
↵
⇡ P2) when they are similar and
P1
↵
⇡ P2 , P1 ' P2 ^ 8P3
164. Types from Declaration
def x : int = 6
def x : int = 6
def f = fun (y : int) { x + y }
Static type-checking (or inference) is one obvious client for name resolution
In many cases, we can perform resolution before doing type analysis
165. Types from Declaration
def x : int = 6
def f = fun (y : int) { x + y }
def f = fun (y : int) { x + y }
def x : int = 6
def f = fun (y : int) { x + y }
Static type-checking (or inference) is one obvious client for name resolution
In many cases, we can perform resolution before doing type analysis
166. Types from Declaration
def x : int = 6
def f = fun (y : int) { x + y }
def x : int = 6
def f = fun (y : int) { x + y }
Static type-checking (or inference) is one obvious client for name resolution
In many cases, we can perform resolution before doing type analysis
167. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
168. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
169. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
170. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
171. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
172. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
173. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
174. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
175. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
176. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
177. Type-Dependent Name Resolution
But sometimes we need types before we can do name resolution
record A1 { x1 : int }
record B1 { a1 : A2 ; x2 : bool}
def z1 : B2 = ...
def y1 = z2.x3
def y2 = z3.a2.x4
Our approach: interleave partial name resolution with type resolution
(also using constraints)
See PEPM 2016 paper / talk
180. Summary: A Theory of Name Resolution
• Representation: Scope Graphs
- Standardized representation for lexical scoping structure of programs
- Path in scope graph relates reference to declaration
- Basis for syntactic and semantic operations
• Formalism: Name Binding Constraints
- References + Declarations + Scopes + Reachability + Visibility
- Language-specific rules map AST to constraints
• Language-Independent Interpretation
- Resolution calculus: correctness of path with respect to scope graph
- Name resolution algorithm
- Alpha equivalence
- Mapping from graph to tree (to text)
- Refactorings
- And many other applications
181. Validation
• We have modeled a large set of example binding patterns
- definition before use
- different let binding flavors
- recursive modules
- imports and includes
- qualified names
- class inheritance
- partial classes
• Next goal: fully model some real languages
- Java
- ML
182. Future Work
• Scope graph semantics for binding specification languages
- starting with NaBL
- or rather: a redesign of NaBL based on scope graphs
• Resolution-sensitive program transformations
- renaming, refactoring, substitution, …
• Dynamic analogs to static scope graphs
- how does scope graph relate to memory at run-time?
• Supporting mechanized language meta-theory
- relating static and dynamic bindings