ChucK : Language Specification > Import System
| |
| |
Import System The @import system
imports classes and operator overloads from other ChucK (.ck) and chugin (.chug) files; it is
designed to facilitate creating, using, and distributing multi-file programs and libraries.
View sample code for importing files
syntax@import statements can appear anywhere in .ck file, so long as they are on the top-most scope. Some example usage of @import: // import a ChucK file (.ck) @import "Foo.ck" // import a chugin (.chug or .chug.wasm) @import "Bar.chug" // multiple imports can be grouped together @import { "AAA.ck", "BBB.chug", "CCC" } // can use implicit filename (with no extension) // if the file 'Blarg' exists, it will be imported as a .ck file // if not, @import will automatically match for .ck and .chug files @import "Blarg" // import a file using absolute path @import "/Users/ge/chuck/examples/import/foo-user.ck" // paths are relative to the location of the container .ck file @import "../dir/Blarg.ck" what gets imported?The @import system imports all public—and only public—class definitions and operator overloads from imported ChucK files. For example: in Foo.ck// define a public Foo class (picked up by @import) public class Foo { // member variable int num; // constructor fun Foo( int n ) { n => num; } } // a non-public class definition (ignored by @import) class Bar { // ... } // public operator overloading + for Foo (picked up by @import) public Foo @operator +( Foo lhs, Foo rhs ) { // return a new Foo return new Foo( lhs.num + rhs.num ); } // non-public binary operator overload for '=>' (ignored by @import) fun void @operator =^( Foo lhs, Foo rhs ) { // for sake of example, just print contents <<< lhs.num, "=^", rhs.num >>>; }in test.ck // import Foo.ck @import "Foo.ck" // instantiate class defined in imported file Foo a(1), b(2); // use operator overload defined in imported file <<< (a + b).num >>>;Imports works recursively; it is possible to @import files that @import other files, etc. There is built-in cycle-detection; if an @import cycle is detected, a compiler error will be issued. Imports are resolved at compile-time, before the rest of the host file is evaluated; this makes it possible for a a host .ck file to @import one or more files and make use of their contents immediately (when it comes to dependency management, this compile-time import mechanism is more powerful than the run-time Machine.add()). If the imported file is a chugin (.chug) file, @import will resolve the filename (see next section for details) and load the chugin. Unlike .ck files, all contents that a chugin adds to the ChucK type system will be imported. filename resolutionIt is possible to import a filename without an extension. As an example, if a host .ck file contains this statement:@import "Blarg"In this case, the @import system will attempt to automatically locate and resolve "Blarg"—to either a .ck file or a .chug file, while taking import paths into account. More specifically, the import system will attempt to locate on disk (starting from the directory where the host .ck file resides) and match for different extensions—e.g., "Blarg", "Blarg.ck", "Blarg.chug", and "Blarg.chug.wasm" (for WebChucK)—resolving "Blarg" to the first matching file. If no match is found, the import system will expand the search to platform-specific search paths. public classesAs of ChucK 1.5.4.0, the restriction of one-public-class-per-file is lifted, making it possible to define multiple public classes in the same .ck file.While non-public classes are not imported, they can used from public classes in the same file. For example: in Bar.ck // non-public class used by Bar class Blarg { // member int num; // constructor fun Blarg( int n ) { n => num; } } // public class public class Bar { // member Blarg blarg(5); }As a somewhat more practical example, ks-chord.ck (a four-voice Karplus Strong chord filter) defines a public KSChord class, which in turns makes use of a non-public KS class. A host file that @import "ks-chord.ck" would be able to instantiate KSChord objects—but not KS objects. CAVEATS: public classes cannot access local variables (i.e., file-scope variables defined outside of class definitions). In general, non-public classes can access local variable—as long as the containing file is not being imported. This restriction is necessary because imported files have no file-level environment of their own. For example: in Bar-Error.ck // a local variable (to the file, defined outside of classes) int theVar; // non-public class used by Bar class Blarg { // ERROR: if this file is imported, will result in compiler error // (due to local variable `theVar` not being recognized) theVar + 1 => int num; } // public class public class Bar { // member Blarg blarg; } additional usage notes@import only adds new definitions to the type system, and will never automatically run any code; client code must first instantiate class or use an operator to execute the contents of imported files.This makes it possible to write unit-test code for public classes in the same file in which it is defined; any code outside of public class/operator definition will NOT be type-checked or run (this code will only scanned for syntax): Bar.ck // a class definition (public; will be picked by @import) public class Bar extends Chugraph { // ... } // unit-test or provide example for KS (will be ignored by @import) Bar bar => dac; // ... | |
| |