Skip to content

importing sympl libraries and accessing and invoking their globals

Stéphane Lozier edited this page Jan 18, 2021 · 1 revision

9 Importing Sympl Libraries and Accessing and Invoking Their Globals

Most of the ground work for importing libraries and accessing other file module's globals has been done. Section on Import code generation discusses some of how this works too. Since file scopes are ExpandoObjects, their DynamicMetaObjects handle the member accesses. When Sympl imports another file of Sympl code, Sympl stores into the importing file's globals scope the name of the file (no directory or extension) using the imported file's module object (an ExpandoObject) as the value. Sympl code can then just dot into these like any other object with members.

Sympl adapts a trick from python for loading files from the same directory that contains the Sympl file doing the importing . You can see in the code excerpt in section that Sympl stores into each file's module globals a special name, "__file__", bound to the full path of the source file. If you look at the RuntimeHelpers.SymplImport in runtime.cs, you can see it fetches this name to build a path for importing a library of Sympl code.

The rest of the support for fetching library globals just falls out of emitting GetMember DynamicExpressions. At this point in Sympl's implementation, the SymplGetMemberBinder still just conveys the name and ignoreCase metadata for binding. That changes after Sympl adds type instantiation, coming up next.

The InvokeMember story is a bit different. Consider this Sympl code:

(imports lists)

(lists.append '(a b c) '(1 2 3))

Sympl compiles "(lists.append" to an InvokeMember DynamicExpression. The meta-object for the 'lists' module's ExpandoObject gets calls to bind the InvokeMember operation. ExpandoObject's don't supply a 'this' or otherwise have a notion of InvokeMember. They do a GetMember using the name on the binder and then call the binder's FallbackInvoke method. FallbackInvoke can just invoke the object received as the target argument. FallbackInvoke for some languages might check to see if the object is a special runtime callable object with special calling conventions or properties. This is described more fully in section .

At this point in Sympl's implementation evolution, its SymplInvokeMemberBinder had a FallbackInvokeMember method that just returned the result of CreateThrow. Its FallbackInvoke method was essentially:

return new DynamicMetaObject(

Expression.Dynamic(

new SymplInvokeBinder(new CallInfo(args.Length)),

typeof(object),

argexprs),

targetMO.Restrictions.Merge(

BindingRestrictions.Combine(args)));

This was not only enough to get cross-library calls working, it became the final implementation. The code in SymplInvokeBinder.FallbackInvoke (discussed in section ) is doing all the work in the nested CallSite resulting from this DynamicExpression.

SymPL Implementation on the Dynamic Language Runtime

Frontmatter
1 Introduction
  1.1 Sources
  1.2 Walkthrough Organization
2 Quick Language Overview
3 Walkthrough of Hello World
  3.1 Quick Code Overview
  3.2 Hosting, Globals, and .NET Namespaces Access
    3.2.1 DLR Dynamic Binding and Interoperability -- a Very Quick Description
    3.2.2 DynamicObjectHelpers
    3.2.3 TypeModels and TypeModelMetaObjects
    3.2.4 TypeModelMetaObject's BindInvokeMember -- Finding a Binding
    3.2.5 TypeModelMetaObject.BindInvokeMember -- Restrictions and Conversions
  3.3 Import Code Generation and File Module Scopes
  3.4 Function Call and Dotted Expression Code Generation
    3.4.1 Analyzing Function and Member Invocations
    3.4.2 Analyzing Dotted Expressions
    3.4.3 What Hello World Needs
  3.5 Identifier and File Globals Code Generation
  3.6 Sympl.ExecuteFile and Finally Running Code
4 Assignment to Globals and Locals
5 Function Definition and Dynamic Invocations
  5.1 Defining Functions
  5.2 SymplInvokeBinder and Binding Function Calls
6 CreateThrow Runtime Binding Helper
7 A Few Easy, Direct Translations to Expression Trees
  7.1 Let* Binding
  7.2 Lambda Expressions and Closures
  7.3 Conditional (IF) Expressions
  7.4 Eq Expressions
  7.5 Loop Expressions
8 Literal Expressions
  8.1 Integers and Strings
  8.2 Keyword Constants
  8.3 Quoted Lists and Symbols
    8.3.1 AnalyzeQuoteExpr -- Code Generation
    8.3.2 Cons and List Keyword Forms and Runtime Support
9 Importing Sympl Libraries and Accessing and Invoking Their Globals
10 Type instantiation
  10.1 New Keyword Form Code Generation
  10.2 Binding CreateInstance Operations in TypeModelMetaObject
  10.3 Binding CreateInstance Operations in FallbackCreateInstance
  10.4 Instantiating Arrays and GetRuntimeTypeMoFromModel
11 SymplGetMemberBinder and Binding .NET Instance Members
12 ErrorSuggestion Arguments to Binder FallbackX Methods
13 SymplSetMemberBinder and Binding .NET Instance Members
14 SymplInvokeMemberBinder and Binding .NET Member Invocations
  14.1 FallbackInvokeMember
  14.2 FallbackInvoke
15 Indexing Expressions: GetIndex and SetIndex
  15.1 SymplGetIndexBinder's FallbackGetIndex
  15.2 GetIndexingExpression
  15.3 SymplSetIndexBinder's FallbackSetIndex
16 Generic Type Instantiation
17 Arithmetic, Comparison, and Boolean Operators
  17.1 Analysis and Code Generation for Binary Operations
  17.2 Analysis and Code Generation for Unary Operations
  17.3 SymplBinaryOperationBinder
  17.4 SymplUnaryOperationBinder
18 Canonical Binders or L2 Cache Sharing
19 Binding COM Objects
20 Using Defer When MetaObjects Have No Value
21 SymPL Language Description
  21.1 High-level
  21.2 Lexical Aspects
  21.3 Built-in Types
  21.4 Control Flow
    21.4.1 Function Call
    21.4.2 Conditionals
    21.4.3 Loops
    21.4.4 Try/Catch/Finally and Throw
  21.5 Built-in Operations
  21.6 Globals, Scopes, and Import
    21.6.1 File Scopes and Import
    21.6.2 Lexical Scoping
    21.6.3 Closures
  21.7 Why No Classes
  21.8 Keywords
  21.9 Example Code (mostly from test.sympl)
22 Runtime and Hosting
  22.1 Class Summary
23 Appendixes
  23.1 Supporting the DLR Hosting APIs
    23.1.1 Main and Example Host Consumer
    23.1.2 Runtime.cs Changes
    23.1.3 Sympl.cs Changes
    23.1.4 Why Not Show Using ScriptRuntime.Globals Namespace Reflection
    23.1.5 The New DlrHosting.cs File
  23.2 Using the Codeplex.com DefaultBinder for rich .NET interop
  23.3 Using Codeplex.com Namespace/Type Trackers instead of ExpandoObjects
  23.4 Using Codeplex.com GeneratorFunctionExpression


Other documents:

Dynamic Language Runtime
DLR Hostirng Spec
Expression Trees v2 Spec
Getting Started with the DLR as a Library Author
Sites, Binders, and Dynamic Object Interop Spec

Clone this wiki locally