For AI agents: This document provides a deep-dive analysis of Eagle's
[object]command internals, including all 43 sub-commands, the opaque object handle system (ObjectDictionary→ObjectWrapper→ObjectData), handle naming (Type#Nformat), theFixupReturnValuepipeline (decides handle creation vs. string return, alias attachment, reference counting), method overload resolution viaFindMethodsAndFixupArguments(parameter type matching, params arrays, by-ref arguments), theObjectFlagsenum (40+ flags controlling disposal, aliasing, naming, references),MarshalFlags(30+ flags controlling method resolution and type conversion),ByRefArgumentFlags, command alias dispatch,IObject/IObjectDatainterfaces, assembly loading with trust verification, namespace imports, type aliases, reference counting (permanent and temporary), and theDefault→Engine→File→Profile→Shell→Core→Consolehost integration. For basic command syntax, seecore_language.md. For usage examples, seecore_examples.md. For workflow patterns, seetips_and_tricks.md.
The Eagle [object] command is the gateway to the entire .NET Common
Language Runtime (CLR) from script level. It provides 43 sub-commands
for creating .NET objects, invoking methods and properties, managing
object lifecycle, loading assemblies, importing namespaces, and
performing reflection — all through a system of opaque string handles
that bridge the managed/.NET world and the script world.
Tcl has no built-in .NET integration (Tcl uses extensions like tclOO
for object orientation, and separate packages for .NET bridging). Eagle's
[object] command is a first-class, deeply integrated .NET interop system
with sophisticated method overload resolution, reference counting,
automatic disposal, and command alias creation.
The command carries CommandFlags.Unsafe | CommandFlags.Critical | CommandFlags.NonStandard and belongs to the "managedEnvironment" object group.
It is not available in safe interpreters by default, though the
policy subsystem may grant access to it in specific contexts.
Key differentiators from Tcl:
| Area | Tcl | Eagle |
|---|---|---|
| .NET object creation | None (requires extension) | [object create] with constructor overload resolution |
| Method invocation | None | [object invoke] with 40+ options, overload resolution |
| Object lifecycle | None | Reference counting, auto-disposal, IDisposable support |
| Assembly loading | None | [object load] with trust/strong-name verification |
| Type resolution | None | Namespace imports, type aliases, assembly scanning |
| Reflection | None | [object members], [object search], [object interfaces] |
| Collection iteration | None | [object foreach] / [object lmap] over IEnumerable |
| Command aliases | None | Objects usable as commands via -alias option |
| By-ref parameters | None | Automatic output parameter → variable mapping |
| Static members | None | object invoke TypeName StaticMember |
| Remote objects | None | [object get] via Activator.GetObject() |
| Assembly verification | None | [object verifyall], [object certificate], [object strongname] |
Eagle bridges .NET and script worlds through opaque string handles.
When a .NET object enters the script world (via [object create], return
values from [object invoke], etc.), the FixupReturnValue pipeline:
- Wraps the .NET object in an
ObjectData→_Objects.Default→ObjectWrapperthree-layer structure - Stores it in the interpreter's
ObjectDictionaryunder a generated handle name - Returns the handle string to the script
Handle names follow the format Type#N where dots in the type name are
replaced with #:
System.Text.StringBuilder → System#Text#StringBuilder#1
System.DateTime → System#DateTime#2
System.Int32 → Int32#3For types from the Eagle runtime assembly, short type names are used
(e.g., StringBuilder#1). Types from other assemblies use the fully
qualified name (e.g., System#Text#StringBuilder#1).
The special handle "null" is a read-only opaque object handle that resolves
to an internal value of null. An empty string "" does not represent null —
when passed where an Interpreter-typed parameter is expected, it is
converted to the active interpreter instance.
FixupReturnValue in MarshalOps.cs is the central decision point for
every .NET value entering the script world. Its decision tree:
- Null value → return the special
"null"handle name (unless-createforces handle creation) - String value → return as-is (unless
-createforces handle) - Enum or simple type → return string representation (unless
-create) - Complex object →
a. Check if an existing handle already references this object
b. If reusable handle found → return existing handle name
c. Otherwise → create new handle via
AddObject()d. If-aliasrequested → create command alias viaAddObjectAlias()e. Return handle name (or alias name ifReturnAliasflag set)
Key decisions are controlled by ObjectFlags:
| Flag | Effect on FixupReturnValue |
|---|---|
ForceNew |
Always create new handle, never reuse |
AllowExisting |
Reuse existing handle if no specific name given |
Alias |
Create a command alias for this handle |
StickAlias |
Automatically create alias on every return |
NoDispose |
Mark handle as non-disposable |
AddReference |
Start reference count at 1 instead of 0 |
NoAttribute |
Skip ObjectFlagsAttribute on the type |
When an object is created with -alias, a command is registered whose
name is the handle (or a custom name via -objectname). Invoking the
alias command dispatches to [object invoke] with the handle pre-filled:
object create -alias System.Text.StringBuilder
# Creates handle "System#Text#StringBuilder#1" AND a command of that name
# These are equivalent:
object invoke System#Text#StringBuilder#1 Append "Hello"
System#Text#StringBuilder#1 Append "Hello"The alias command accepts the same options as [object invoke] — put them
right after the alias. The alias's pre-filled arguments (the handle) and the
call-site arguments, options included, are combined by Interpreter.MergeArguments
into a well-formed list before dispatch, so -parametertypes and every other
option behave identically to the long form:
# Pin an overload through the alias — identical to the long form below:
System#Text#StringBuilder#1 -parametertypes {System.String} Append 65
object invoke -parametertypes {System.String} System#Text#StringBuilder#1 Append 65Aliases support namespace mapping via [object aliasnamespaces] — assembly
names can be mapped to Eagle namespace prefixes.
FindMethodsAndFixupArguments in MarshalOps.cs (~1,500 lines) is the
method overload resolution engine. For each candidate method:
- Name matching — filter by method name
- Parameter count — check argument count fits min/max (accounting
for optional parameters and
paramsarrays) - Type hint matching — if
-parametertypesprovided, verify against method signature - Argument conversion — for each formal parameter:
- Pointer types → reject (forbidden)
paramsarray → collect remaining arguments, convert each to element type- By-ref parameters → verify variable exists, create
ArgumentInfofor post-call variable update - Regular parameters → call
FixupArgumentfor type conversion (includes opaque handle lookup)
- Success criteria — all arguments converted, return type matches
Multiple successful matches are ordered by ReorderFlags preferences
(parameter count, type specificity, etc.) and the first (or indexed)
match is selected.
| File | Role |
|---|---|
Commands/Object.cs (~5,616 lines) |
Command implementation: 43 sub-commands |
Components/Private/MarshalOps.cs (~11,000+ lines) |
Marshalling: FixupReturnValue, FindMethodsAndFixupArguments, type resolution, handle naming |
Components/Private/ObjectOps.cs (~7,177 lines) |
Option definitions, defaults, disposal helpers |
Components/Public/ObjectData.cs |
IObjectData implementation: handle metadata |
Containers/Public/ObjectDictionary.cs |
Handle storage: Dictionary<string, object> |
Components/Public/Interpreter.cs |
AddObject, RemoveObject, AddObjectAlias, reference counting |
Components/Public/Enumerations.cs |
ObjectFlags, MarshalFlags, ObjectOptionType, ValueFlags, ByRefArgumentFlags |
Interfaces/Public/Object.cs |
IObject interface |
Interfaces/Public/ObjectData.cs |
IObjectData interface |
These are the most important sub-commands. They form the fundamental create → use → dispose workflow.
object create ?options? typeName ?arg ...?Purpose: Create a new instance of a .NET type by resolving the type name, finding a matching constructor, converting arguments, and returning an opaque object handle.
Options:
| Option | Type | Purpose |
|---|---|---|
-objectname |
string | Explicit handle name (instead of auto-generated) |
-type |
Type | Explicit type hint |
-objecttypes |
TypeList | Type list for object value resolution |
-methodtypes |
TypeList | Type list for method matching |
-parametertypes |
TypeList | Constructor parameter types for overload resolution |
-parametermarshalflags |
MarshalFlags list | Per-parameter marshalling control |
-marshalflags |
MarshalFlags | Method resolution flags |
-reorderflags |
ReorderFlags | Method match ordering |
-objectvalueflags |
ValueFlags | Value interpretation flags |
-argumentflags |
ByRefArgumentFlags | By-ref argument handling |
-flags / -bindingflags |
BindingFlags | .NET reflection binding flags |
-objectflags |
ObjectFlags | Handle creation flags |
-byrefobjectflags |
ObjectFlags | Flags for by-ref output handles |
-limit |
integer | Maximum candidate methods to consider |
-index |
integer | Force selection of Nth matching constructor |
-alias |
switch | Create command alias for the handle |
-aliasraw |
switch | Alias dispatches to invokeraw |
-aliasall |
switch | Alias dispatches to invokeall |
-aliasreference |
switch | Alias holds an object reference |
-nocreate |
switch | Don't create (return constructor info only) |
-noinvoke |
switch | Don't invoke constructor |
-help |
switch | Don't invoke; return help for the matching constructor overload(s) |
-noargs |
switch | Ignore constructor arguments |
-nodispose |
switch | Mark handle as non-disposable |
-noforcedelete |
switch | Don't force-delete on removal |
-tostring |
switch | Convert result to string instead of handle |
-arrayasvalue |
switch | Use handles for managed array outputs |
-arrayaslink |
switch | Link to underlying array element |
-nomutatebindingflags |
switch | Don't modify binding flags |
-stricttype |
switch | Strict type name matching |
-strictmember |
switch | Strict constructor matching |
-strictargs |
switch | Strict argument matching |
-nocase |
switch | Case-insensitive type/member matching |
-nobyref |
switch | Skip by-ref argument handling |
-default |
switch | Use default type resolution |
-verbose |
switch | Verbose error messages |
-debug |
switch | Debug output |
-trace |
switch | Trace output |
-tcl |
TclInterpreter | Tcl bridge target (requires NATIVE && TCL) |
Implementation flow:
- Resolve
typeNameto a .NETTypeviaValue.GetAnyType()— searches imported namespaces, type aliases, loaded assemblies - If the type is a simple/value type with no arguments, use
Activator.CreateInstance(type) - Otherwise, get all constructors via reflection
- Call
FindMethodsAndFixupArguments()to find matching constructors and convert script arguments to .NET types - Select the best match (by index, limit, or automatic ordering)
- If neither
-noinvokenor-helpis set, invoke the constructor - Pass result through
FixupReturnValueto create handle and optional alias - Fix up any by-ref argument variables
The -help option resolves the constructor overloads exactly as a real call
would (honoring the arguments, -index, -parametertypes, and so on) but, rather
than invoking, returns their documentation as a logical list of help data -- one
or more entries, one per matching overload, each carrying that member's summary,
parameters, returns, and any other elements -- drawn from the assembly's XML
documentation file. It is the documentation-returning twin of -noinvoke, and the
same option is accepted by [object invoke] and [library call].
# Basic creation
set sb [object create System.Text.StringBuilder]
# With constructor arguments
set sb [object create System.Text.StringBuilder "Initial text"]
# With explicit parameter types for overload resolution
set dt [object create -parametertypes {System.Int32 System.Int32 System.Int32} \
System.DateTime 2024 1 15]
# With alias (creates a command)
object create -alias System.Collections.ArrayList
# With custom handle name
set obj [object create -objectname myObj System.Object]
# Non-disposable handle
set cfg [object create -nodispose System.Configuration.Something]object invoke ?options? object member ?arg ...?Purpose: Invoke a method, get/set a property, or access a field on a .NET object or type. This is the primary sub-command for all .NET interaction after object creation.
Options (combined from InvokeOnly + InvokeShared + FixupReturnValue):
| Option | Type | Purpose |
|---|---|---|
-type |
Type | Override object type |
-objecttype |
Type | Explicit object type |
-proxytype |
Type | Proxy type for transparent proxies |
-objecttypes |
TypeList | Type list for object resolution |
-methodtypes |
TypeList | Type list for method matching |
-parametertypes |
TypeList | Parameter types for overload resolution |
-parametermarshalflags |
MarshalFlags list | Per-parameter marshalling |
-marshalflags |
MarshalFlags | Method resolution control |
-reorderflags |
ReorderFlags | Match ordering |
-objectvalueflags |
ValueFlags | Value interpretation |
-membervalueflags |
ValueFlags | Member name interpretation |
-argumentflags |
ByRefArgumentFlags | By-ref argument handling |
-flags / -bindingflags |
BindingFlags | .NET binding flags |
-objectflags |
ObjectFlags | Return value handle flags |
-byrefobjectflags |
ObjectFlags | By-ref output handle flags |
-membertypes |
MemberTypes | Filter: Method, Property, Field, etc. |
-returntype |
Type | Expected return type |
-objectname |
string | Explicit handle name for return value |
-limit |
integer | Max candidate methods |
-index |
integer | Force Nth match |
-alias |
switch | Alias the return value |
-aliasraw |
switch | Return alias dispatches to invokeraw |
-aliasall |
switch | Return alias dispatches to invokeall |
-aliasreference |
switch | Return alias holds reference |
-create |
switch | Force handle creation for return value |
-nodispose |
switch | Return handle is non-disposable |
-noforcedelete |
switch | Don't force-delete return handle |
-tostring |
switch | Convert return value to string |
-noinvoke |
switch | Don't invoke (return member info only) |
-help |
switch | Don't invoke; return help for the matching member(s) |
-noargs |
switch | Ignore arguments |
-nobyref |
switch | Skip by-ref handling |
-nonestedmember |
switch | Don't navigate nested members (e.g., Prop.SubProp) |
-nonestedobject |
switch | Don't navigate nested object handles |
-stricttype |
switch | Strict type matching |
-strictmember |
switch | Strict member matching |
-strictargs |
switch | Strict argument matching |
-nocase |
switch | Case-insensitive matching |
-default |
switch | Use default type resolution |
-verbose |
switch | Verbose errors |
-debug |
switch | Debug output |
-trace |
switch | Trace output |
-identity |
switch | Return the object itself (no member access) |
-typeidentity |
switch | Return the object's type |
-invokeraw |
switch | Redirect to invokeraw |
-invokeall |
switch | Redirect to invokeall |
-arrayasvalue |
switch | Use handles for array outputs |
-arrayaslink |
switch | Link to array elements |
-datetimekind |
DateTimeKind | DateTime interpretation |
-datetimestyles |
DateTimeStyles | DateTime parsing style |
-datetimeformat |
string | DateTime format string |
-tcl |
TclInterpreter | Tcl bridge target |
Member resolution:
The [object] argument can be either an opaque handle (for instance
members) or a type name (for static members). The member argument
names the method, property, or field. Nested member navigation is
supported: Prop.SubProp.Method.
Member types:
| Member type | Read (0 extra args) | Write (1 extra arg) |
|---|---|---|
| Field | Get field value | Set field value |
| Property | Get property value | Set property value |
| Method | Invoke with 0 args | Invoke with args |
| Event | Get event info | Add/remove handler |
By-ref argument handling:
When a method has out or ref parameters, Eagle automatically:
- Creates
ArgumentInfotracking for each by-ref parameter - After invocation, writes output values back to script variables
- Output values pass through
FixupReturnValue(creating handles for complex types)
# Instance method
set sb [object create System.Text.StringBuilder]
object invoke $sb Append "Hello"
set result [object invoke $sb ToString]
# Static method
set sqrt [object invoke System.Math Sqrt 144.0]
# Static property
set now [object invoke System.DateTime Now]
set nl [object invoke System.Environment NewLine]
# Property get/set
set len [object invoke $sb Length]
object invoke $sb Length 10 ;# Set property
# By-ref / out parameter
object invoke System.Int32 TryParse "42" result
# $result now contains the parsed value
# With explicit parameter types
object invoke -parametertypes {string int} $obj Method "hello" 42
# Return value as alias
set list [object invoke -alias $obj GetList]
$list Add "item" ;# Use alias directly
# Nested member navigation
object invoke $obj Config.Settings.Value
# Type identity
set type [object invoke -typeidentity $obj ignored]object invokeraw ?options? object member ?arg ...?Purpose: Invoke a member via Type.InvokeMember() directly, without
Eagle's argument conversion pipeline. Useful when you need exact control
over the reflection call.
Has the same options as [object invoke] except -invokeraw is ignored
(since you're already using it), -invoke redirects the entire call back to
[object invoke], and -invokeall redirects it to [object invokeall].
Cross-reference: the
-invokeand-invokeallredirects re-dispatch the whole sub-command (a recursive call with the sub-command name replaced), so[object invokeraw -invoke ...]accepts everything[object invoke]does -- including-help. That is why[object invokeraw]does not list-helpitself: it reaches it through-invoke.
# Direct invocation without type conversion
object invokeraw $obj MethodName arg1 arg2object invokeall ?options? object memberAndArgs ?memberAndArgs ...?Purpose: Invoke multiple members on the same object in sequence.
Each memberAndArgs is a list where the first element is the member
name and the rest are arguments.
Return value: by default [object invokeall] returns a two-element list
{overallCode errorCount} -- the overall completion code (Ok when every member
invocation succeeded, Error when any failed) and the number of failed
invocations (e.g. {Ok 0}). -keepresults instead returns a flat list of
{code result} pairs, one per member (e.g. {Ok 0 Ok 0}); -lastresult returns
only the final member's result. Each member is dispatched internally through
[object invoke].
Additional options (beyond invoke):
| Option | Type | Purpose |
|---|---|---|
-chained |
switch | Each result becomes the next invocation's object |
-lastresult |
switch | Return only the last result |
-keepresults |
switch | Keep all results as a list |
-nocomplain |
switch | Ignore invocation errors |
-invoke |
switch | Redirect the entire call to [object invoke] |
-invokeraw |
switch | Redirect the entire call to [object invokeraw] |
Cross-reference:
-invokeand-invokerawhere are not per-element mode switches -- when present, they re-dispatch the whole sub-command (a recursive call with the sub-command name replaced), so[object invokeall -invoke ...]runs as a single[object invoke ...]and accepts everything it does, including-help.-invokeallitself is ignored (you are already using it).
# Multiple method calls
set sb [object create System.Text.StringBuilder]
object invokeall $sb {Append Hello} {Append " "} {Append World}
set result [object invoke $sb ToString]
# Chained calls (result of each becomes object for next)
set result [object invokeall -chained $obj \
{GetBuilder} {Append Hello} {ToString}]A member call is routed to one of [object invoke], [object invokeraw], or
[object invokeall] through three independent axes, listed in increasing
precedence:
| Axis | Set via | Effect |
|---|---|---|
| 1. Sub-command name | typing [object invoke], [object invokeraw], or [object invokeall] |
The variant you name directly. |
| 2. Alias default | -alias (optionally with -aliasraw / -aliasall) at [object create] or [object invoke] time |
What the created command dispatches to: plain -alias uses invoke, -aliasraw uses invokeraw, -aliasall uses invokeall (recorded on the alias as the ByRefArgumentFlags.AliasRaw / AliasAll flags). |
| 3. Per-call override | -invoke / -invokeraw / -invokeall on an individual call |
Re-dispatches that single call to the named variant, overriding axes 1 and 2. |
The same -invoke / -invokeraw / -invokeall vocabulary drives both the
sub-command redirect (on [object invoke] and friends) and the alias override,
so it only has to be learned once.
Worked example (verified by test object-3.3):
set x [object create -alias System.Int32] ;# alias uses [object invoke] (the default)
set y [object create -alias -aliasall System.Int32] ;# alias uses [object invokeall]
$x ToString ;# -> 0 (single invoke)
$y ToString ;# -> {Ok 0} (invokeall reports {overallCode errorCount})
$x -invokeall ToString ToString ToString ;# per-call override -> {Ok 0}
$y -invoke ToString X ;# per-call override -> 0 (a single invoke)
$x ToString ToString ToString ;# error: a single invoke cannot take three arguments
$y ToString ToString ToString ;# -> {Ok 0} (invokeall runs all three members)A few consequences worth noting:
- Axis 3 always wins. An
-aliasallcommand still performs a single invoke for a call made with-invoke, and an ordinary invoke alias runs a wholeinvokeallfor a call made with-invokeall. - As an axis-3 override,
-invoke/-invokeraw/-invokeallon[object invokeall]or[object invokeraw]are whole-command redirects (see those sub-commands), not per-member mode switches. - The alias options themselves are documented under
[object create]; the flags they set live in theByRefArgumentFlagsenum.
object dispose ?options? object ?object ...?Purpose: Call Dispose() on IDisposable objects and remove their
handles from the interpreter. Accepts multiple objects.
Options:
| Option | Type | Purpose |
|---|---|---|
-synchronous |
switch | Synchronous disposal (no deferred GC) |
-nodispose |
switch | Remove handle but don't call Dispose() |
-nocomplain |
switch | Ignore errors during disposal |
Disposal pipeline:
- For each object argument, calls
MaybeRemoveObject() - Checks if object is locked (locked objects cannot be removed)
- If
dispose=trueandObjectFlags.NoDisposeis not set:- Calls
IDisposable.Dispose()on the wrapped .NET object
- Calls
- Removes the command alias (if one exists)
- Removes from
ObjectDictionary - Returns
disposed N removed Mcounts (no braces; a count of 1 is omitted, e.g.removed,disposed removed,disposed 2 removed 2)
Disposal control flags:
| ObjectFlag | Effect |
|---|---|
NoDispose |
Dispose() is never called on this object |
NoAutoDispose |
Automatic disposal is suppressed (object may not be owned) |
AutoDispose |
Force automatic disposal |
Locked |
Object cannot be removed or disposed at all |
# Basic disposal
object dispose $stream
# Dispose multiple objects
object dispose $obj1 $obj2 $obj3
# Remove handle without calling Dispose()
object dispose -nodispose $handle
# Ignore errors
object dispose -nocomplain $maybeDisposed
# Canonical try/finally pattern
try {
set stream [object create System.IO.FileStream test.txt Create]
# ... use stream ...
} finally {
if {[info exists stream]} then {
object dispose $stream
}
}object foreach ?options? varName object body
object lmap ?options? varName object bodyPurpose: Iterate over any IEnumerable .NET object. [foreach]
evaluates the body for each element; [lmap] collects results.
Options:
| Option | Type | Purpose |
|---|---|---|
-collect |
boolean | Collect results (default: true for [lmap], false for [foreach]) |
-synchronous |
switch | Synchronous disposal of iteration handles |
-objectname |
string | Custom handle name for each element |
-type |
Type | Expected element type |
-objectflags |
ObjectFlags | Flags for element handles |
-nocreate |
switch | Don't create handles for simple types |
-nodispose |
switch | Don't dispose element handles after body |
-nocase |
switch | Case-insensitive type matching |
-alias |
switch | Alias each element handle |
-aliasraw |
switch | Element alias uses invokeraw |
-aliasall |
switch | Element alias uses invokeall |
-aliasreference |
switch | Element alias holds reference |
-noforcedelete |
switch | Don't force-delete element handles |
-tostring |
switch | Convert elements to string |
-tcl |
TclInterpreter | Tcl bridge target |
Implementation:
- Gets
IEnumerableinterface from the object - Calls
GetEnumerator()to obtainIEnumerator - Loops calling
MoveNext():- Each element passes through
FixupReturnValue - Sets
varNamein the caller's scope - Evaluates
body - Handles
[break],[continue],[return],[error]
- Each element passes through
- Respects interpreter iteration limit
- For
[lmap]: collects body results into a list
set list [object create System.Collections.ArrayList]
object invoke $list Add "one"
object invoke $list Add "two"
object invoke $list Add "three"
# Iterate (each element is a fresh opaque handle, e.g. System#String#NNNN)
object foreach item $list {
puts "Item: $item" ;# prints handles, not "one"/"two"/"three"
}
# Use -tostring to get the element string values
object foreach -tostring item $list {
puts "Item: $item" ;# prints: Item: one, Item: two, Item: three
}
# Collect transformed results (-tostring converts elements to strings)
set upper [object lmap -tostring item $list {
string toupper $item
}]
;# Returns: {ONE TWO THREE}object fromvar ?options? varNamePurpose: Create an object handle from a variable's value. Useful when a variable already contains a handle string and you need to re-wrap or re-alias it.
Options include the standard return-value options (-alias, -objectflags,
-objectname, -tostring, etc.).
object load ?options? assemblyPurpose: Load a .NET assembly into the current AppDomain, optionally importing its namespaces and declaring its interfaces.
Options:
| Option | Type | Purpose |
|---|---|---|
-loadtype |
LoadType | How to load: PartialName, FullName, File, Bytes, Stream |
-namespace |
string | Alias namespace for assembly |
-reflectiononly |
switch | Reflection-only load (no execution) |
-fromobject |
switch | Load from object stream |
-trustedonly |
switch | Require trust verification |
-maybetrustedonly |
switch | Trust verification if available |
-verifiedonly |
switch | Require strong name verification |
-maybeverifiedonly |
switch | Strong name verification if available |
-import |
switch | Import namespaces from assembly |
-importnonpublic |
switch | Include non-public namespaces |
-importmode |
MatchMode | Import pattern matching mode |
-importpattern |
string | Namespace filter pattern |
-importnocase |
switch | Case-insensitive import |
-declare |
switch | Declare interfaces from assembly |
-declarenonpublic |
switch | Include non-public interfaces |
-declaremode |
MatchMode | Declare pattern matching mode |
-declarepattern |
string | Interface filter pattern |
-declarenocase |
switch | Case-insensitive declare |
-objectflags |
ObjectFlags | Handle flags (default includes Assembly) |
-objectname |
string | Custom handle name |
-alias |
switch | Create alias for assembly handle |
-aliasraw / -aliasall / -aliasreference |
switch | Alias options |
-create |
switch | Force handle creation |
-nodispose |
switch | Non-disposable handle |
-noforcedelete |
switch | Don't force-delete |
-tostring |
switch | Convert to string |
-tcl |
TclInterpreter | Tcl bridge target |
Load types:
| LoadType | Method | Security |
|---|---|---|
PartialName |
Assembly.LoadWithPartialName() |
None |
FullName |
Assembly.Load() |
None |
File |
Assembly.LoadFrom() |
Trust + strong name verification available |
Bytes |
Assembly.Load(byte[]) |
None |
Stream |
Load from object stream | None |
# Load by name
object load System.Data
# Load from file with verification
object load -loadtype File -trustedonly -verifiedonly MyPlugin.dll
# Load and import namespaces
object load -import System.Data
set dt [object create DataTable] ;# Short name works
# Load and declare interfaces
object load -declare -import System.Dataobject import ?options? ?name name ...?
object unimport ?options?Purpose: Import .NET namespaces so types can be referenced by short
names (e.g., StringBuilder instead of System.Text.StringBuilder).
[object import] options:
| Option | Type | Purpose |
|---|---|---|
-matchmode |
MatchMode | Pattern matching mode |
-container |
string | Container namespace |
-pattern |
string | Namespace filter pattern |
-eagle |
switch | Import Eagle internal namespaces |
-clr |
switch | Import standard CLR namespaces |
-nocase |
switch | Case-insensitive matching |
[object unimport] options:
| Option | Type | Purpose |
|---|---|---|
-matchmode |
MatchMode | Pattern matching mode |
-pattern |
string | Namespace filter pattern |
-nocase |
switch | Case-insensitive matching |
-values |
switch | Match by values instead of keys |
# Import specific namespaces
object import System.Text System.IO System.Collections.Generic
# Now use short names
set sb [object create StringBuilder "Hello"]
# Import Eagle namespaces
object import -eagle
# Remove imports
object unimport -pattern "System.Text"object type ?options? ?fromName toName ...? fromName toName
object untype ?options?Purpose: Register custom type name mappings. Takes pairs of
fromName toName arguments.
# Register short names
object type SB System.Text.StringBuilder
object type AL System.Collections.ArrayList
set sb [object create SB] ;# Uses the alias
# Remove aliases
object untype -pattern "SB"object declare ?options? ?name name ...?
object undeclare ?options?Purpose: Declare interfaces that the type resolution system should be aware of.
object search ?options? typeNamePurpose: Search for a type by name across all loaded assemblies. Returns the resolved type information.
Options:
| Option | Type | Purpose |
|---|---|---|
-objecttypes |
TypeList | Type list to search |
-stricttype |
switch | Strict matching |
-nocase |
switch | Case-insensitive |
-noshowname |
switch | Don't show name in results |
-nonamespace |
switch | Omit namespace |
-noassembly |
switch | Omit assembly |
-noexception |
switch | Omit exceptions |
-fullname |
switch | Use fully qualified names |
object search System.Text.StringBuilder
object search -nocase stringbuilderobject resolve assemblyPurpose: Resolve an assembly reference to its full name.
object assemblies ?pattern?Purpose: List all assemblies loaded in the current AppDomain, optionally filtered by pattern.
| Sub-command | Syntax | Returns |
|---|---|---|
object exists object |
Check handle validity | Boolean |
object isnull ?options? object |
Check if null or disposed | Boolean |
object isdisposed ?options? object |
Check if value is disposed | Boolean |
object isoftype ?options? object type |
Instance-of check | Boolean |
object list ?pattern? |
List all handles | Handle list |
object flags object ?flags? |
Get/set ObjectFlags |
Flags value |
object referencecount object |
Get reference count | Integer |
[object isnull] options:
| Option | Purpose |
|---|---|
-nocomplain |
Don't error if handle not found |
-objectdisposed |
Check wrapper disposal state |
-valuedisposed |
Check wrapped value disposal state |
-force |
Force disposal check |
-cannotcheck |
Default value if check impossible |
-caughtexception |
Default value if exception caught |
[object isdisposed] options: Same as isnull disposal options.
[object isoftype] options:
| Option | Purpose |
|---|---|
-objecttypes |
Type list to check |
-stricttype |
Strict type matching |
-nocase |
Case-insensitive |
-nocomplain |
Ignore type resolution errors |
-assignable |
Check assignable compatibility (not just exact type) |
if {[object exists $obj]} {
if {![object isnull $obj]} {
if {[object isoftype $obj System.IDisposable]} {
object dispose $obj
}
}
}object members ?options? objectPurpose: List members (methods, properties, fields, events) of an object or type via reflection.
Options:
| Option | Type | Purpose |
|---|---|---|
-membertypes |
MemberTypes | Filter: Method, Property, Field, Event, etc. |
-mode |
MatchMode | Pattern matching mode |
-pattern |
string | Member name filter |
-flags / -bindingflags |
BindingFlags | .NET binding flags |
-attributes |
switch | Include attribute information |
-signatures |
switch | Include method signatures |
-qualified |
switch | Use fully qualified type names |
-nameonly |
switch | Return names only |
-matchnameonly |
switch | Match against name only |
-stricttype |
switch | Strict type matching |
-nocase |
switch | Case-insensitive matching |
-verbose |
switch | Verbose output |
# List all members
object members $obj
# List methods only
object members -membertypes Method $obj
# List with signatures
object members -signatures -membertypes Method $obj
# Filter by pattern
object members -pattern "Get*" $objobject interfaces ?pattern? ;# List declared interfaces
object namespaces ?pattern? ;# List imported namespaces
object types ?pattern? ;# List type aliasesobject alias ?options? object
object unalias objectPurpose: Create or remove a command alias for an existing object handle.
[object alias] options:
| Option | Purpose |
|---|---|
-objecttypes |
Type list for matching |
-aliasname |
Custom alias name |
-verbose |
Verbose output |
-stricttype |
Strict matching |
-nocase |
Case-insensitive |
-aliasraw |
Raw formatting |
-aliasall |
Alias all matches |
-aliasreference |
Create reference alias |
# Create alias for existing handle
object alias -aliasname myObj $handle
# Use alias
myObj ToString
myObj SomeMethod arg1 arg2
# Remove alias
object unalias myObjobject aliasnamespaces ?pattern?
object unaliasnamespace ?options?Purpose: Manage namespace mappings for object aliases. When an alias is created, the assembly name can be mapped to an Eagle namespace prefix.
object addreference object
object removereference object
object referencecount objectPurpose: Manually manage reference counts. Adding a reference prevents automatic cleanup; removing allows it.
Reference types (internal ObjectReferenceType):
| Type | When used |
|---|---|
Create |
Initial handle creation |
Demand |
[object addreference] |
Trace |
[set] trace on variable containing handle |
Return |
[return] of handle value |
Command |
Alias command creation |
# Prevent cleanup
object addreference $longLived
# ... much later ...
object removereference $longLived
object dispose $longLivedobject cleanup ?options?Options:
| Option | Type | Purpose |
|---|---|---|
-pattern |
string | Match handles by pattern |
-referencecount |
integer | Only clean up objects with this reference count |
-references |
switch | Clean up references too |
-noremove |
switch | Don't remove from dictionary |
-nodispose |
switch | Don't dispose objects |
-synchronous |
switch | Synchronous cleanup |
-nocomplain |
switch | Ignore errors |
Returns disposed N removed M.
# Clean up all unreferenced objects
object cleanup -referencecount 0
# Clean up matching pattern
object cleanup -pattern "*StringBuilder*"
# Full cleanup
object cleanup -references -synchronousobject verifyall ?options?Purpose: Verify all loaded assemblies for strong names, signatures, and certificates.
object certificate ?options? assemblyPurpose: Get X.509 certificate information for an assembly.
Options:
| Option | Purpose |
|---|---|
-chain |
Verify certificate chain |
-x509verificationflags |
X.509 verification flags |
-x509revocationmode |
Certificate revocation mode |
-x509revocationflag |
Revocation flag |
object hash assembly
object strongname assemblyPurpose: Get hash or strong name information for an assembly.
Requires CAS_POLICY compile flag.
object callbackflags name ?flags?
object removecallback namePurpose: Get/set callback flags or remove a named callback. Callbacks are created when Eagle wraps script procedures as .NET delegates.
object get ?options? type url ?state?Purpose: Get a proxy to a remote .NET object via URL using
Activator.GetObject(). Not available on .NET Standard 2.0.
ObjectFlags is a [Flags] ulong with 40+ values controlling every
aspect of handle behavior.
| Flag | Purpose |
|---|---|
NoDispose |
Dispose() is never called |
AutoDispose |
Force automatic disposal when handle removed |
NoAutoDispose |
Prevent automatic disposal (object may not be owned) |
ForceDelete |
Force removal from dictionary |
Locked |
Cannot be removed or disposed |
| Flag | Purpose |
|---|---|
Alias |
Object has a command alias |
StickAlias |
Automatically create alias on every return |
UnstickAlias |
Forbid creating alias even if StickAlias set |
ReturnAlias |
Return the alias name instead of handle name |
| Flag | Purpose |
|---|---|
AddReference |
Start reference count at 1 |
NoReturnReference |
Don't add reference on [return] |
TemporaryReturnReference |
[return] references are temporary |
| Flag | Purpose |
|---|---|
ForceNew |
Always create new handle (never reuse) |
AllowExisting |
Allow reusing existing handle |
ForceAutomaticName |
Always use auto-generated name |
ForceManualName |
Always use explicit name |
| Flag | Purpose |
|---|---|
NoBinder |
Don't use custom binder |
NoAttribute |
Skip ObjectFlagsAttribute on type |
NoComObjectLookup |
Don't look up COM types |
NoComObjectReturn |
Don't wrap COM return values |
AllowProxyGetType |
Allow GetType() on transparent proxies |
ForceProxyGetType |
Force GetType() on transparent proxies |
| Flag | Purpose |
|---|---|
Safe |
Safe for use in safe interpreters |
WellKnown |
Well-known system object |
Assembly |
Loaded assembly handle |
Runtime |
Runtime-created object |
Application |
Application-level object |
Interpreter |
Interpreter-owned object |
MarshalFlags controls method overload resolution and type conversion.
| Flag | Purpose |
|---|---|
StrictMatchCount |
Parameter count must match exactly |
StrictMatchType |
Parameter types must match exactly |
ForceParameterType |
Force use of specified parameter types |
SelectMethodIndex |
Force selection of specific method index |
ReorderMatches |
Reorder matches by ReorderFlags criteria |
SortMembers |
Sort candidates by name and parameter count |
ReverseOrder |
Prefer methods with more parameters |
MinimumOptionalCount |
Prefer methods with more optional parameters |
AllowAnyMethod |
Skip method access checks |
| Flag | Purpose |
|---|---|
NoByRefArguments |
Skip output parameter handling |
UseInOnly |
Use only ParameterInfo.IsIn for input determination |
UseByRefOnly |
Use only Type.IsByRef for output determination |
HandleByValue |
Resolve opaque handles to values |
ByValHandleByValue |
By-value handles resolve to values |
ByRefHandleByValue |
By-ref handles resolve to values |
ForceHandleByValue |
Force all handles to resolve to values |
| Flag | Purpose |
|---|---|
NoDelegateCallback |
Don't create delegate callbacks |
NoGenericCallback |
Don't create generic callbacks |
DynamicCallback |
Use dynamic method for callback |
SimpleCallback |
Look up pre-existing method |
ReturnICallback |
Return ICallback instead of Delegate |
MarshalFlags.Default = StrictMatchCount | StrictMatchType | ThrowOnBindFailure
Controls how by-ref (output/ref) parameters are handled.
| Flag | Purpose |
|---|---|
Fast |
Skip traces, watches, notifications |
Direct |
Bypass SetVariableValue |
Strict |
Strict type handling |
Create |
Object creation expected |
Dispose |
Dispose if creation fails |
Alias |
Create command alias for output |
AliasRaw |
Alias uses invokeraw |
AliasAll |
Alias uses invokeall |
AliasReference |
Alias holds object reference |
ToString |
Convert to string and discard handle |
ArrayAsValue |
Use handles for managed arrays |
ArrayAsLink |
Link to underlying array elements |
NoSetVariable |
Skip setting the output variable |
# 1. Load assembly (if not already loaded)
object load System.Data
# 2. Import namespaces for short names
object import System.Text System.IO
# 3. Create instance
set sb [object create StringBuilder "Hello"]
# 4. Call methods and properties
object invoke $sb Append ", World!"
set result [object invoke $sb ToString]
;# Returns: Hello, World!
# 5. Clean up
object dispose $sb# Create with alias
object create -alias System.Collections.ArrayList
# Use alias as command (dispatches to [object invoke])
ArrayList#1 Add "item1"
ArrayList#1 Add "item2"
set count [ArrayList#1 Count]
# Custom alias name
object create -alias -objectname myList System.Collections.ArrayList
myList Add "hello"# Static methods (use type name as object)
set sqrt [object invoke System.Math Sqrt 144.0]
set guid [object invoke System.Guid NewGuid]
# Static properties
set now [object invoke System.DateTime Now]
set nl [object invoke System.Environment NewLine]
set cores [object invoke System.Environment ProcessorCount]# Single resource
try {
set stream [object create System.IO.MemoryStream]
object invoke $stream WriteByte 65
object invoke $stream WriteByte 66
} finally {
if {[info exists stream]} then {
object dispose $stream
}
}
# Multiple resources
try {
set resources [list]
lappend resources [object create System.IO.FileStream \
$inputFile Read]
lappend resources [object create System.IO.FileStream \
$outputFile Write]
# ... use resources ...
} finally {
if {[info exists resources]} then {
foreach resource $resources {
catch {object dispose $resource}
}
}
}# Let Eagle resolve automatically
set dt [object create System.DateTime 2024 1 15]
# Explicit parameter types when ambiguous
set dt [object create -parametertypes {System.Int32 System.Int32 System.Int32} \
System.DateTime 2024 1 15]
# Force specific constructor index
set obj [object create -index 2 MyType arg1 arg2]set list [object create System.Collections.ArrayList]
object invoke $list Add "alpha"
object invoke $list Add "beta"
object invoke $list Add "gamma"
# Iterate (each element is a fresh opaque handle; use -tostring for values)
object foreach -tostring item $list {
puts "Item: $item"
}
# Collect transformed results (-tostring converts elements to strings)
set upper [object lmap -tostring item $list {
string toupper $item
}]
# Iterate with alias for each element
object foreach -alias item $list {
$item ToString ;# Use alias on each element
}# Int32.TryParse has an 'out' parameter
object invoke System.Int32 TryParse "42" result
# $result now contains the parsed value
# Dictionary.TryGetValue
object invoke $dict TryGetValue "key" value
# $value contains the result if key found# Create generic List<string>
set list [object create -alias \
"System.Collections.Generic.List\`1\[System.String\]"]
$list Add "hello"
$list Add "world"
set count [$list Count]The [object] command is marked CommandFlags.Unsafe | CommandFlags.Critical | CommandFlags.NonStandard and is not available in safe interpreters by default.
However, the policy subsystem may grant access to it, subject to heavy restrictions:
- Only types and members explicitly allowed by active policies can be accessed
- Assembly loading may be restricted or forbidden
- Certain
ObjectFlagsare markedUnsafein option definitions and are unavailable in safe interpreters - Options marked
Unsafein the option dictionary (shown withUnsafeflag) are silently ignored or rejected in safe mode
The policy system uses PolicyOps to check every type resolution,
member invocation, and assembly load against registered policies.
| Feature | Tcl approach | Eagle [object] approach |
|---|---|---|
| Object creation | tclOO: oo::class create |
object create TypeName ?args? (any .NET type) |
| Method calls | $obj method args |
object invoke $obj method args |
| Properties | Manual getter/setter | object invoke $obj Prop / object invoke $obj Prop val |
| Static members | N/A | object invoke TypeName Member |
| Type checking | N/A | object isoftype $obj Type |
| Reflection | info class (limited) |
object members -signatures $obj |
| Disposal | N/A | [object dispose] with IDisposable support |
| Assembly loading | [package require] |
[object load] with trust verification |
| Namespace import | N/A | [object import] for short type names |
| Collection iteration | Manual | [object foreach] / [object lmap] over IEnumerable |
| Type aliases | N/A | object type shortName fullName |
| By-ref parameters | N/A | Automatic output → variable mapping |
| Reference counting | N/A | [object addreference] / [object removereference] |
| Command aliases | N/A | -alias creates callable command from handle |
| Remote objects | N/A | object get type url via Activator.GetObject() |
| Certificate verification | N/A | object certificate -chain assembly |
- The command is
Unsafebut can be policy-granted — policies control which types, members, and assemblies are accessible object load -trustedonly -verifiedonlyenforces trust and strong name verification on file-loaded assembliesObjectFlags.Lockedprevents script-level disposal of critical objectsObjectFlags.NoDisposeprevents accidental disposal of shared objects- By-ref argument handling can modify script variables — ensure output variable names are intended
[object invokeraw]bypasses Eagle's type conversion safety, exposing raw .NET reflection[object get](remote activation) connects to external services — validate URLs- Command aliases execute with the creating interpreter's privileges
- Assembly verification via
[object verifyall]can audit loaded code