Skip to content

Commit

Permalink
basic @import functionality (#467)
Browse files Browse the repository at this point in the history
* expose chugin load API; initial runtime Machine.import()

* add webchuck/emscripten API for importChugin()

* add parser and AST support for @import

* expand @import syntax; prep for import scans

* add preliminary import scan

* fix midifile-play.ck example link

* basic import functionality with topological sort; compiler and parser interface rework

* added import unit tests

* modify import parsing: semicolon now optional; for now, must enclose import target in string literal

* import error reporting, part 1

* import error reporting, part 2; cycles and containers

* modify import error reporting; more unit tests

* add import target node for more specific error reporting

* add lines for @import error reporting

* add pre-generated yacc parser

* fix windows-specific import path issues

* fix windows implicit path e.g., A --> A.ck

* add namespace to string in chuck.cpp

* prune import code

* add import unit tests for operators

* oops add unit test dependency

* fix emscripten loadModule() stub

---------

Co-authored-by: nshaheed <[email protected]>
  • Loading branch information
gewang and nshaheed authored Oct 18, 2024
1 parent 2d525b5 commit 334b10c
Show file tree
Hide file tree
Showing 54 changed files with 3,295 additions and 2,003 deletions.
4 changes: 3 additions & 1 deletion VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ ChucK VERSIONS log
1.5.3.3
=======
- (fixed) specific internal UGen connection error now handled without exiting
- (fixed, windows) single letter filenames without extensions (e.g., "A") now
are distinguished from windows drive letters (e.g., "A:\")


1.5.3.2 (October 2024)
=======
*** ChuGL maintanance patch ***
- (updated) backend WebGPU version to wgpu-22.1.0.5
- (added) OpenGL fallback on machines where modern graphics APIs (vulkan, metal, direct3d)
are not supported
are not supported
- (fixed) shreds can now exit a GG.nextFrame() loop without hanging the window
- (added) GG.unregisterShred() to manually unregister a graphics shred
- (added) new examples
Expand Down
28 changes: 7 additions & 21 deletions src/core/chuck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,11 +764,9 @@ t_CKBOOL ChucK::initChugins()
// push indent
EM_pushlog();

// SPENCERTODO: what to do for full path
std::string full_path = filename;

// parse, type-check, and emit
if( compiler()->go( filename, full_path ) )
// NOTE: filename here should already be a fullpath
if( compiler()->compileFile( filename ) )
{
// preserve op overloads | 1.5.1.5
compiler()->env()->op_registry.preserve();
Expand Down Expand Up @@ -1167,12 +1165,8 @@ t_CKBOOL ChucK::compileFile( const std::string & path,
goto error;
}

// construct full path to be associated with the file so me.sourceDir() works
// (added 1.3.0.0)
full_path = get_full_path(filename);

// parse, type-check, and emit (full_path added 1.3.0.0)
if( !m_carrier->compiler->go( filename, full_path ) )
if( !m_carrier->compiler->compileFile( filename ) )
goto error;

// get the code
Expand Down Expand Up @@ -1265,7 +1259,7 @@ t_CKBOOL ChucK::compileCode( const std::string & code,
EM_pushlog();

// falsify filename / path for various logs
std::string theThing = "compiled.code:" + argsTogether;
std::string theThing = std::string(CHUCK_CODE_LITERAL_SIGNIFIER) + ":" + argsTogether;
std::string fakefakeFilename = "<result file name goes here>";

// parse out command line arguments
Expand All @@ -1277,22 +1271,14 @@ t_CKBOOL ChucK::compileCode( const std::string & code,
goto error;
}

// working directory
workingDir = getParamString( CHUCK_PARAM_WORKING_DIRECTORY );

// construct full path to be associated with the file so me.sourceDir() works
full_path = workingDir + "/compiled.code";
// log
EM_log( CK_LOG_FINE, "full path: %s...", full_path.c_str() );

// parse, type-check, and emit (full_path added 1.3.0.0)
if( !m_carrier->compiler->go( "<compiled.code>", full_path, code ) )
// parse, type-check, and emit
if( !m_carrier->compiler->compileCode( code ) )
goto error;

// get the code
vm_code = m_carrier->compiler->output();
// (re) name it (no path to append) | 1.5.0.5 (ge) update from '+=' to '='
vm_code->name = "compiled.code";
vm_code->name = CHUCK_CODE_LITERAL_SIGNIFIER;

// log
EM_log( CK_LOG_FINE, "sporking %d %s...", count,
Expand Down
3 changes: 3 additions & 0 deletions src/core/chuck.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
#define CHUCK_PARAM_USER_CHUGINS CHUCK_PARAM_CHUGIN_LIST_USER
#define CHUCK_PARAM_USER_CHUGIN_DIRECTORIES CHUCK_PARAM_CHUGIN_LIST_USER_DIR

// code literal signifier
#define CHUCK_CODE_LITERAL_SIGNIFIER "<compiled.code>"




Expand Down
1 change: 1 addition & 0 deletions src/core/chuck.lex
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ global { adjust(); return GLOBAL; }
"@operator" { adjust(); return AT_OP; }
"@construct" { adjust(); return AT_CTOR; }
"@destruct" { adjust(); return AT_DTOR; }
"@import" { adjust(); return AT_IMPORT; }
"->" { adjust(); return ARROW_RIGHT; }
"<-" { adjust(); return ARROW_LEFT; }
"-->" { adjust(); return GRUCK_RIGHT; }
Expand Down
32 changes: 26 additions & 6 deletions src/core/chuck.y
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ a_Program g_program = NULL;
a_Complex complex_exp;
a_Polar polar_exp;
a_Vec vec_exp; // ge: added 1.3.5.3
a_Import import; // 1.5.2.5 (ge) added
};

// expect shift/reduce conflicts
Expand All @@ -107,7 +108,8 @@ a_Program g_program = NULL;
// 1.4.0.0: changed to 41 for global keyword
// 1.4.0.1: changed to 79 for left recursion
// 1.5.1.1: changed to 80 for trailing comma in array literals
%expect 82
// 1.5.2.5: changed to 84 for @import statements
%expect 84

%token <sval> ID STRING_LIT CHAR_LIT
%token <ival> INT_VAL
Expand Down Expand Up @@ -135,7 +137,7 @@ a_Program g_program = NULL;
PUBLIC PROTECTED PRIVATE STATIC ABSTRACT CONST
SPORK ARROW_RIGHT ARROW_LEFT L_HACK R_HACK
GRUCK_RIGHT GRUCK_LEFT UNGRUCK_RIGHT UNGRUCK_LEFT
AT_OP AT_CTOR AT_DTOR
AT_OP AT_CTOR AT_DTOR AT_IMPORT


%type <program> program
Expand All @@ -156,6 +158,7 @@ a_Program g_program = NULL;
%type <stmt> selection_statement
%type <stmt> jump_statement
%type <stmt> expression_statement
%type <stmt> import_statement
%type <exp> expression
%type <exp> chuck_expression
%type <exp> arrow_expression
Expand Down Expand Up @@ -197,6 +200,8 @@ a_Program g_program = NULL;
%type <complex_exp> complex_exp
%type <polar_exp> polar_exp
%type <vec_exp> vec_exp // ge: added 1.3.5.3
%type <import> import_target // 1.5.2.5 (ge) added
%type <import> import_list // 1.5.2.5 (ge) added

%start program

Expand Down Expand Up @@ -355,6 +360,7 @@ statement
| jump_statement { $$ = $1; }
// | label_statement { }
| code_segment { $$ = $1; }
| import_statement { $$ = $1; }
;

jump_statement
Expand All @@ -370,7 +376,7 @@ selection_statement
| IF LPAREN expression RPAREN statement ELSE statement
{ $$ = new_stmt_from_if( $3, $5, $7, @1.first_line, @1.first_column ); }
;

loop_statement
: WHILE LPAREN expression RPAREN statement
{ $$ = new_stmt_from_while( $3, $5, @1.first_line, @1.first_column ); }
Expand All @@ -394,19 +400,33 @@ code_segment
: LBRACE RBRACE { $$ = new_stmt_from_code( NULL, @1.first_line, @1.first_column ); }
| LBRACE statement_list RBRACE { $$ = new_stmt_from_code( $2, @1.first_line, @1.first_column ); }
;


import_statement
: AT_IMPORT import_target { $$ = new_stmt_from_import( $2, @1.first_line, @1.first_column );}
| AT_IMPORT LBRACE import_list RBRACE { $$ = new_stmt_from_import( $3, @1.first_line, @1.first_column );}
;

import_list
: import_target { $$ = $1; }
| import_target COMMA import_list { $$ = prepend_import( $1, $3, @1.first_line, @1.first_column ); }

import_target
: STRING_LIT { $$ = new_import( $1, NULL, @1.first_line, @1.first_column ); }
// | id_dot { $$ = new_import( NULL, $1, @1.first_line, @1.first_column ); }
;

expression_statement
: SEMICOLON { $$ = NULL; }
| expression SEMICOLON { $$ = new_stmt_from_expression( $1, @1.first_line, @1.first_column ); }
;

expression
: chuck_expression { $$ = $1; }
| expression COMMA chuck_expression { $$ = append_expression( $1, $3, @1.first_line, @1.first_column ); }
| expression COMMA chuck_expression { $$ = append_expression( $1, $3, @1.first_line, @1.first_column ); }
;

chuck_expression
: arrow_expression { $$ = $1; }
: arrow_expression { $$ = $1; }
| chuck_expression chuck_operator arrow_expression
{ $$ = new_exp_from_binary( $1, $2, $3, @2.first_line, @2.first_column ); }
;
Expand Down
113 changes: 100 additions & 13 deletions src/core/chuck_absyn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "chuck_errmsg.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string> // 1.5.1.5 for string concat


Expand Down Expand Up @@ -342,23 +343,85 @@ a_Stmt new_stmt_from_case( a_Exp exp, uint32_t lineNum, uint32_t posNum )
return a;
}

a_Stmt new_stmt_from_import( a_Import list, uint32_t line, uint32_t where ) // 1.5.2.5 (ge) added
{
a_Stmt a = (a_Stmt)checked_malloc( sizeof(struct a_Stmt_) );
a->s_type = ae_stmt_import;
a->stmt_import.list = list;
a->line = line; a->where = where;
a->stmt_import.line = line; a->stmt_import.where = where;
a->stmt_import.self = a;

return a;
}

a_Import new_import( c_str str, a_Id_List list, uint32_t line, uint32_t where ) // 1.5.2.5 (ge) added
{
a_Import a = (a_Import)checked_malloc( sizeof(struct a_Import_) );

// check which option
if( str )
{
a->what = str; // no strdup( str ); <-- str should have been allocated in alloc_str()
}
else // id list
{
a_Id_List curr = list;
std::string result = "";

// iterate over id list
while( curr )
{
result += S_name(curr->xid);
// if not the last, appent DOT
if( curr->next ) result += ".";
// set to next
curr = curr->next;
}

// sum of string lengths, +1 for null terminator
size_t len = result.length() + 1;
// allocate
char * sc = (char *)checked_malloc( len );
// copy
strncpy( sc, result.c_str(), len );
// set
a->what = sc;
// clean up id list, since we will not have references to it after this
delete_id_list( list );
}

// set line info
a->line = line; a->where = where;

return a;
}

a_Import prepend_import( a_Import target, a_Import list, uint32_t lineNum, uint32_t posNum )
{
target->next = list;
return target;
}

a_Exp append_expression( a_Exp list, a_Exp exp, uint32_t lineNum, uint32_t posNum )
{
a_Exp current;
current = list->next;
if (current == NULL) {
list->next = exp;
return list;
}
a_Exp current;
current = list->next;
if( current == NULL )
{
list->next = exp;
return list;
}

while (1)
while( true )
{
if (current->next == NULL) {
current->next = exp;
break;
} else {
current = current->next;
}
if( current->next == NULL ) {
current->next = exp;
break;
}
else {
current = current->next;
}
}
return list;
}
Expand Down Expand Up @@ -1306,6 +1369,9 @@ void delete_stmt( a_Stmt stmt )
case ae_stmt_gotolabel:
delete_stmt_from_label( stmt );
break;
case ae_stmt_import:
delete_stmt_from_import( stmt );
break;
}

CK_SAFE_FREE( stmt );
Expand Down Expand Up @@ -1388,6 +1454,27 @@ void delete_stmt_from_label( a_Stmt stmt )
// TODO: someting with S_Symbol stmt->gotolabel.name
}

void delete_stmt_from_import( a_Stmt stmt )
{
EM_log( CK_LOG_FINEST, "deleting stmt %p (import)...", (void *)stmt );

// pointer
a_Import next = NULL, i = stmt->stmt_import.list;

// iterate instead of recurse to avoid stack overflow
while( i )
{
// delete the content
CK_SAFE_FREE( i->what );
// get next before we delete this one
next = i->next;
// delete the import target
CK_SAFE_FREE( i );
// move to the next one
i = next;
}
}

void delete_exp_from_primary( a_Exp_Primary_ & p )
{
EM_log( CK_LOG_FINEST, "deleting exp (primary)..." );
Expand Down
Loading

0 comments on commit 334b10c

Please sign in to comment.