Skip to content

Commit

Permalink
[js] Add start of ESM support
Browse files Browse the repository at this point in the history
See #183
  • Loading branch information
ojwb committed Sep 28, 2023
1 parent 510d933 commit ccdb7f4
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 10 deletions.
26 changes: 24 additions & 2 deletions compiler/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ static int eq(const char * s1, const char * s2) {
return strcmp(s1, s2) == 0;
}

static int startswith(const char * s1, const char * s2) {
return strncmp(s1, s2, strlen(s2)) == 0;
}

static void print_arglist(int exit_code) {
FILE * f = exit_code ? stderr : stdout;
fprintf(f, "Usage: snowball SOURCE_FILE... [OPTIONS]\n\n"
Expand All @@ -49,7 +53,8 @@ static void print_arglist(int exit_code) {
" -py, -python\n"
#endif
#ifndef DISABLE_JS
" -js\n"
" -js[=TYPE] generate Javascript (TYPE values:\n"
" esm global, default: global)\n"
#endif
#ifndef DISABLE_RUST
" -rust\n"
Expand Down Expand Up @@ -115,6 +120,7 @@ static int read_options(struct options * o, int argc, char * argv[]) {
o->output_file = 0;
o->syntax_tree = false;
o->comments = false;
o->js_esm = false;
o->externals_prefix = NULL;
o->variables_prefix = 0;
o->runtime_path = 0;
Expand Down Expand Up @@ -162,6 +168,18 @@ static int read_options(struct options * o, int argc, char * argv[]) {
#ifndef DISABLE_JS
if (eq(s, "-js")) {
o->make_lang = LANG_JAVASCRIPT;
o->js_esm = false;
continue;
}
if (startswith(s, "-js=")) {
o->make_lang = LANG_JAVASCRIPT;
if (eq(s + 4, "global")) {
o->js_esm = false;
} else if (eq(s + 4, "esm")) {
o->js_esm = true;
} else {
fprintf(stderr, "Unknown Javascript type '%s'\n", s + 4);
}
continue;
}
#endif
Expand Down Expand Up @@ -543,7 +561,11 @@ extern int main(int argc, char * argv[]) {
#ifndef DISABLE_JS
if (o->make_lang == LANG_JAVASCRIPT) {
byte * s = add_sz_to_s(0, output_base);
s = add_literal_to_s(s, ".js");
if (o->js_esm) {
s = add_literal_to_s(s, ".mjs");
} else {
s = add_literal_to_s(s, ".js");
}
o->output_src = get_output(s);
lose_s(s);
generate_program_js(g);
Expand Down
29 changes: 22 additions & 7 deletions compiler/generator_js.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,11 +1221,21 @@ static void generate(struct generator * g, struct node * p) {
}

static void generate_class_begin(struct generator * g) {

w(g, "/**@constructor*/~N"
"var ~n = function() {~+~N"
"~Mconst ~P = require('./base-stemmer.js');~N"
"~Mvar base = new ~P();~N");
if (g->options->js_esm) {
w(g, "// deno-lint-ignore-file~N"
"import ~P from './base-stemmer.mjs'~N"
"~N"
"/** @typedef {{ stemWord(word: string): string }} Stemmer */~N"
"~N"
"/** @type {{ new(): Stemmer }} */~N"
"const ~n = function() {~+~N"
"~Mvar base = new ~P();~N");
} else {
w(g, "/**@constructor*/~N"
"var ~n = function() {~+~N"
"~Mconst ~P = require('./base-stemmer.js');~N"
"~Mvar base = new ~P();~N");
}
}

static void generate_class_end(struct generator * g) {
Expand All @@ -1237,8 +1247,13 @@ static void generate_class_end(struct generator * g) {
w(g, "~Mreturn base.getCurrent();~N");
w(g, "~-~M};~N");
w(g, "~-};~N");
w(g, "~N");
w(g, "if (typeof module === 'object' && module.exports) module.exports = ~n;~N");
if (g->options->js_esm) {
w(g, "~N"
"export default ~n~N");
} else {
w(g, "~N"
"if (typeof module === 'object' && module.exports) module.exports = ~n;~N");
}
}

static void generate_among_table(struct generator * g, struct among * x) {
Expand Down
1 change: 1 addition & 0 deletions compiler/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ struct options {
FILE * output_h;
byte syntax_tree;
byte comments;
byte js_esm;
enc encoding;
enum { LANG_JAVA, LANG_C, LANG_CPLUSPLUS, LANG_CSHARP, LANG_PASCAL, LANG_PYTHON, LANG_JAVASCRIPT, LANG_RUST, LANG_GO, LANG_ADA } make_lang;
const char * externals_prefix;
Expand Down
104 changes: 103 additions & 1 deletion javascript/base-stemmer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
// @ts-check

/**@constructor*/
const BaseStemmer = function() {
/** @protected */
this.current = '';
this.cursor = 0;
this.limit = 0;
this.limit_backward = 0;
this.bra = 0;
this.ket = 0;

/**
* @param {string} value
*/
this.setCurrent = function(value) {
this.current = value;
this.cursor = 0;
Expand All @@ -9,11 +22,18 @@ const BaseStemmer = function() {
this.ket = this.limit;
};

/**
* @return {string}
*/
this.getCurrent = function() {
return this.current;
};

/**
* @param {BaseStemmer} other
*/
this.copy_from = function(other) {
/** @protected */
this.current = other.current;
this.cursor = other.cursor;
this.limit = other.limit;
Expand All @@ -22,7 +42,14 @@ const BaseStemmer = function() {
this.ket = other.ket;
};

/**
* @param {number[]} s
* @param {number} min
* @param {number} max
* @return {boolean}
*/
this.in_grouping = function(s, min, max) {
/** @protected */
if (this.cursor >= this.limit) return false;
var ch = this.current.charCodeAt(this.cursor);
if (ch > max || ch < min) return false;
Expand All @@ -32,7 +59,14 @@ const BaseStemmer = function() {
return true;
};

/**
* @param {number[]} s
* @param {number} min
* @param {number} max
* @return {boolean}
*/
this.in_grouping_b = function(s, min, max) {
/** @protected */
if (this.cursor <= this.limit_backward) return false;
var ch = this.current.charCodeAt(this.cursor - 1);
if (ch > max || ch < min) return false;
Expand All @@ -42,7 +76,14 @@ const BaseStemmer = function() {
return true;
};

/**
* @param {number[]} s
* @param {number} min
* @param {number} max
* @return {boolean}
*/
this.out_grouping = function(s, min, max) {
/** @protected */
if (this.cursor >= this.limit) return false;
var ch = this.current.charCodeAt(this.cursor);
if (ch > max || ch < min) {
Expand All @@ -57,7 +98,14 @@ const BaseStemmer = function() {
return false;
};

/**
* @param {number[]} s
* @param {number} min
* @param {number} max
* @return {boolean}
*/
this.out_grouping_b = function(s, min, max) {
/** @protected */
if (this.cursor <= this.limit_backward) return false;
var ch = this.current.charCodeAt(this.cursor - 1);
if (ch > max || ch < min) {
Expand All @@ -72,8 +120,13 @@ const BaseStemmer = function() {
return false;
};

/**
* @param {string} s
* @return {boolean}
*/
this.eq_s = function(s)
{
/** @protected */
if (this.limit - this.cursor < s.length) return false;
if (this.current.slice(this.cursor, this.cursor + s.length) != s)
{
Expand All @@ -83,8 +136,13 @@ const BaseStemmer = function() {
return true;
};

/**
* @param {string} s
* @return {boolean}
*/
this.eq_s_b = function(s)
{
/** @protected */
if (this.cursor - this.limit_backward < s.length) return false;
if (this.current.slice(this.cursor - s.length, this.cursor) != s)
{
Expand All @@ -94,8 +152,13 @@ const BaseStemmer = function() {
return true;
};

/** @return {number} */ this.find_among = function(v)
/**
* @param {Among[]} v
* @return {number}
*/
this.find_among = function(v)
{
/** @protected */
var i = 0;
var j = v.length;

Expand Down Expand Up @@ -165,8 +228,13 @@ const BaseStemmer = function() {
};

// find_among_b is for backwards processing. Same comments apply
/**
* @param {Among[]} v
* @return {number}
*/
this.find_among_b = function(v)
{
/** @protected */
var i = 0;
var j = v.length

Expand Down Expand Up @@ -232,8 +300,15 @@ const BaseStemmer = function() {
/* to replace chars between c_bra and c_ket in this.current by the
* chars in s.
*/
/**
* @param {number} c_bra
* @param {number} c_ket
* @param {string} s
* @return {number}
*/
this.replace_s = function(c_bra, c_ket, s)
{
/** @protected */
var adjustment = s.length - (c_ket - c_bra);
this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket);
this.limit += adjustment;
Expand All @@ -242,8 +317,12 @@ const BaseStemmer = function() {
return adjustment;
};

/**
* @return {boolean}
*/
this.slice_check = function()
{
/** @protected */
if (this.bra < 0 ||
this.bra > this.ket ||
this.ket > this.limit ||
Expand All @@ -254,8 +333,13 @@ const BaseStemmer = function() {
return true;
};

/**
* @param {number} c_bra
* @return {boolean}
*/
this.slice_from = function(s)
{
/** @protected */
var result = false;
if (this.slice_check())
{
Expand All @@ -265,20 +349,34 @@ const BaseStemmer = function() {
return result;
};

/**
* @return {boolean}
*/
this.slice_del = function()
{
/** @protected */
return this.slice_from("");
};

/**
* @param {number} c_bra
* @param {number} c_ket
* @param {string} s
*/
this.insert = function(c_bra, c_ket, s)
{
/** @protected */
var adjustment = this.replace_s(c_bra, c_ket, s);
if (c_bra <= this.bra) this.bra += adjustment;
if (c_bra <= this.ket) this.ket += adjustment;
};

/**
* @return {string}
*/
this.slice_to = function()
{
/** @protected */
var result = '';
if (this.slice_check())
{
Expand All @@ -287,8 +385,12 @@ const BaseStemmer = function() {
return result;
};

/**
* @return {string}
*/
this.assign_to = function()
{
/** @protected */
return this.current.slice(0, this.limit);
};
};
Expand Down

0 comments on commit ccdb7f4

Please sign in to comment.