Skip to content

Commit a1085b1

Browse files
committed
Python dict methods; named radio buttons
1 parent 4b4b3d1 commit a1085b1

18 files changed

+620
-518
lines changed

ForInstalledPython/glow.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/RScompiler.3.2.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/RSrun.3.2.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/compiler.3.2.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline/glowscript_libraries/glow.3.2.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

GlowScriptOffline3.2.zip

1.11 KB
Binary file not shown.

docs/VPythonDocs/controls.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ <h1><font color="#0000A0">Widgets:
108108
<p class="attributes"><font color="#FF0000">checked</font> If True, the radio button is highlighted; default is False. Can be changed at any time.</p>
109109
<p class="attributes"><font color="#FF0000">disabled</font> If True, the radio button is grayed out and the radio button is inactive. Can be changed at any time.</p>
110110
<p class="attributes"><font color="#FF0000">delete()</font> If R is a radio button, R.delete() deletes the radio button from the display.</p>
111+
<p class="attributes"><font color="#FF0000">name</font> If you specify a name (as a string, such as &quot;group&quot;) for several radio buttons, clicking on one of the unhighlighted &quot;group&quot; radio buttons unhighlights all the others. Clicking on an already hightlighted radio button has no effect. If you do not specify a name, radio buttons simply behave as toggles, just like checkbox widgets; the only difference is that radio widgets are round and checkbox widgets are square.The name cannot be changed after creating the radio button.</p>
111112
<p class="Normal"></p>
112113
<p class="Header"><strong><font color="#0000a0">checkbox</font></strong></p>
113114
<p class="Normal">Here are the attributes of a <strong>checkbox</strong> widget:</p>

lib/compiling/GScompiler.js

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,14 @@ Search for "Embedding the RapydScript compiler in your webpage". There you will
3333
with instructions for how to use it. Store the file in lib/rapydscript/compiler.js.
3434
3535
The in-browser transpiler includes a minimized copy of the run-time function. However, for a program exported
36-
to the user's own web page, the transpiler is not present and a run-time file is need. Here is how to build
37-
the rapydscript-ng runtime library (but see below for an alternative procedure):
38-
1) Make sure node is installed.
39-
2) In a new folder, execute "npm install rapydscript-ng".
40-
3) Create a file named "input.py" in this folder that contains "a=1".
41-
4) Execute this (modify if not on Windows): node.exe .\node_modules\rapydscript-ng\bin\rapydscript --bare input.py > runtime.js
42-
5) At the end of the file "runtime.js", delete these lines:
43-
var __name__ = "__main__";
44-
45-
var a;
46-
a = 1;
47-
6) Copy the file to lib/rapydscript/runtime.js.
48-
For GlowScript 3.1 runtime.js had the encoding "UCS-2 LE BOM" which the Uglify
49-
machinery could not handle. Using (on Windows) notepad++ the encoding was changed
50-
to "UTF-8" which solved the problem.
51-
52-
The instructions above for building the two RapydScript files are adequate if it is not necessary to
36+
to the user's own web page, the transpiler is not present and a run-time file is needed:
37+
Copy the Github file release/baselib-plain-pretty.js to lib/runtime.js.
38+
39+
===========================================================================================
40+
The instructions above for obtaining the two RapydScript files are adequate if it is not necessary to
5341
get the very latest version from the rapydscript-ng repository. If there have been commits to the
5442
repository that you want, but the key files haven't been updated, replace the instructions with the
55-
following. If on Windows, omit "sudo" from commands.
43+
following. If on Windows, omit "sudo" from commands, and change "/" to "\" in file names.
5644
5745
Build rapydscript-ng from source (from "Installation" section at rapydscript-ng):
5846
1) Make sure node and git are installed.
@@ -64,25 +52,24 @@ Build rapydscript-ng from source (from "Installation" section at rapydscript-ng)
6452
3) Execute "sudo bin/rapydscript self --complete --test". This will build files in the "release" folder.
6553
6654
Build embedded compiler: (from "Embedding the RapydScript compiler in your webpage" section at rapydscript-ng)
67-
4) Execute "sudo bin/web-repl-export embedded". This builds the "embedded" (in-browser) compiler.
55+
4) Execute "sudo bin/web-repl-export embed". In the (new) folder "embed" the file rapydscript.js is the
56+
(in-browser) compiler. In December 2021 this did NOT work on Windows and had to be done on a Mac.
6857
6958
Move new files to glowscript source:
70-
5) Copy the file dev/baselib-plain-pretty.js to lib/rapydscript and change the name to runtime.js.
71-
6) Copy the file embedded/rapydscript.js to lib/rapydscript and change the name to compiler.js.
72-
7) If not already present, insert these statements at the start of runtime.js (this is a kludge; don't know how to invoke the new compiler):
73-
var ρσ_iterator_symbol = (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") ? Symbol.iterator : "iterator-Symbol-5d0927e5554349048cf0e3762a228256";
74-
var ρσ_kwargs_symbol = (typeof Symbol === "function") ? Symbol("kwargs-object") : "kwargs-object-Symbol-5d0927e5554349048cf0e3762a228256";
75-
var ρσ_cond_temp, ρσ_expr_temp, ρσ_last_exception;
76-
var ρσ_object_counter = 0;
59+
5) Copy the file release/baselib-plain-pretty.js to lib/rapydscript runtime.js.
60+
6) Copy the file embed/rapydscript.js to lib/rapydscript/compiler.js.
61+
62+
However you obtain the two RapydScript-NG files, you need to make the following changes
63+
in order to enable tests for two vectors being equal or unequal:
7764
7865
Make RapydScript-NG handle vec == vec and vec != vec:
79-
In lib/rapydscript/compiler.js, search for "function ρσ_equals" (two places)
66+
In lib/rapydscript/compiler.js, search for "function ρσ_equals"
8067
and insert the following string just before "if (a === b)"
8168
if (a instanceof vec) {\n if (!(b instanceof vec)) return false;\nreturn (a.x === b.x && a.y === b.y && a.z === b.z);\n}\n
8269
8370
In lib/rapydscript/compiler.js, search for "function ρσ_not_equals" (two places)
8471
and insert the following string just before "if (a === b)"
85-
if (a instanceof vec) {\n if (!(b instanceof vec)) return true;\nreturn (a.x !== b.x || a.y !== b.y || a.z !== b.z);\n}\n
72+
if (a instanceof vec) {\n if (!(b instanceof vec)) return true;\nreturn (a.x !== b.x || a.y !== b.y || a.z !== b.z);\n}\n
8673
8774
In lib/rapydscript/runtime.js, search for "function ρσ_equals"
8875
and insert the following code just before "if (a === b)"
@@ -98,6 +85,17 @@ and insert the following code just before "if (a === b)"
9885
return (a.x !== b.x || a.y !== b.y || a.z !== b.z);
9986
}
10087
88+
Also, you need to change .pop to .pypop in the two RapydScript-NG files (GScompiler.js converts all occurrences of .pop to .pypop).
89+
In lib/rapydscript/compiler.js:
90+
Search for "ans.pop = ρσ_list_pop;" and change ans.pop to ans.pypop in two places.
91+
Search for "ρσ_set.prototype.pop" and change pop to pypop in two places.
92+
Search for "ρσ_dict.prototype.pop" and change pop to pypop in two places.
93+
In lib/rapydscript/runtime.js:
94+
Search for "ans.pop = ρσ_list_pop" and change ans.pop to ans.pypop.
95+
Search for "ρσ_set.prototype.pop" and change pop to pypop.
96+
Search for "ρσ_dict.prototype.pop" and change pop to pypop.
97+
===========================================================================================
98+
10199
OPERATOR OVERLOADING
102100
For operator overloading, the source for lib/compiling/papercomp.js is at https://github.com/paperjs/paper.js,
103101
at src/core/PaperScript.js; compare with papercomp.js, which was modified by Bruce Sherwood for greater speed.
@@ -763,8 +761,9 @@ where compile() was called, in untrusted/run.js.
763761
program = program.replace(/\.delete/g, ".remove")
764762

765763
function pop_replace(m, p1, p2) {
766-
if (p2.length === 0) return m
767-
else return '.py'+m.slice(1)
764+
// if (p2.length === 0) return m // pop()
765+
// else return '.py'+m.slice(1) // pop(n)
766+
return '.py'+m.slice(1)
768767
}
769768

770769
const vp_primitives = ["arrow", "box", "compound", "cone", "curve", "cylinder", "ellipsoid", "extrusion",
@@ -783,12 +782,17 @@ where compile() was called, in untrusted/run.js.
783782
compile_rapydscript(program)
784783
} else {// handle Python imports
785784
var prog
786-
// if pop(), leave as is to work ok with both lists and sets, but if pop(N), which is only found with lists, use pypop(N)
785+
// If pop(), leave as is to work ok with both lists and sets (but not dicts),
786+
// but if pop(N), which is found with lists but not sets, use pypop(N).
787+
// A difficulty is that pop with Python-like dictionaries has the form pop(attribute),
788+
// which should return the value of that attribute.
787789
program = program.replace(/(\.pop\s*\(\s*)([^)]*)/g, pop_replace)
790+
788791
program = program.replace(/\.sort\s*\(/g, '.pysort(') // Make sort equivalent to pysort (RapydScript python-like sort)
789792
prog = "def __main__():\n version = "+version+"\n"
790-
// The following turned out to slow all calculations down by about a factor of 5 and so was abandoned:
791-
//prog += " from __python__ import dict_literals, overload_getitem\n" // so that dictionaries behave like Python dictionaries
793+
794+
prog += " from __python__ import dict_literals, overload_getitem\n" // so that dictionaries behave like Python dictionaries
795+
792796
prog += " window.__GSlang = 'vpython'\n" // WebGLRenderer needs to know at run time what models to create
793797
// let hasvec = (VPython_names.indexOf('vec') >= 0)
794798
// let hasvector = (VPython_names.indexOf('vector') >= 0)
@@ -870,7 +874,7 @@ where compile() was called, in untrusted/run.js.
870874
program = program.replace(/\* _GSpow_ \*/g, '**') // restore x**n
871875

872876
// handle operator overloading
873-
var start = program.indexOf("async function __main__()")
877+
start = program.indexOf("async function __main__()")
874878
var prog = program.slice(start)
875879
prog = papercompile(prog)
876880
prog = program.slice(0,start)+prog
@@ -887,7 +891,8 @@ where compile() was called, in untrusted/run.js.
887891
'shapes', 'helix', 'ring', 'compound', 'vertex', 'triangle', 'quad', 'label',
888892
'distant_light', 'local_light', 'attach_trail', 'attach_arrow', 'text', 'extrusion',
889893
'wtext', 'winput', 'radio', 'checkbox', 'button', 'slider', 'menu', 'input', 'js_generator', 'yield',
890-
'mag', 'mag2', 'norm', 'hat', 'dot', 'cross', 'proj', 'diff_angle', 'abs', 'filter',
894+
'clear', 'copy', 'get', 'items', 'keys', 'values', 'pypop', 'popitem', 'fromkeys', 'update', 'setdefault',
895+
'mag', 'mag2', 'norm', 'hat', 'dot', 'cross', 'proj', 'diff_angle', 'abs', 'filter', 'set',
891896
'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2', 'exp', 'log', 'pow', 'sqrt',
892897
'ceil', 'floor', 'sign', 'round', 'max', 'min', 'random', "factorial", "combin"]
893898

@@ -946,6 +951,7 @@ where compile() was called, in untrusted/run.js.
946951
start += m.index+name.length+1
947952
continue
948953
}
954+
949955
// If this is a class, delete the call to __init__ (we will insert this call after creating the class instance)
950956
if (options.lang == 'vpython' && !period && classes.indexOf(name) >= 0) {
951957
start += m.index+name.length+1
@@ -991,6 +997,10 @@ where compile() was called, in untrusted/run.js.
991997
}
992998

993999
let pstart = ptr+1 // start of ....f()
1000+
if (prog.slice(pstart, pstart+11) == 's.jsset.add') { // this is a set
1001+
start += m.index+name.length+1
1002+
continue
1003+
}
9941004
let prefix = ''
9951005
if (period) {
9961006
// paths and shapes are lists which need to be converted to RapydScript lists to have methods such as insert
@@ -1067,7 +1077,8 @@ where compile() was called, in untrusted/run.js.
10671077
let no_await2 = ['remove', 'select', 'append_to_title', 'append_to_caption', 'bind', 'unbind', 'call', 'append',
10681078
'rgb_to_hsv', 'hsv_to_rgb', 'mag', 'mag2', 'norm', 'hat', 'rotate', 'random', 'pow', 'equals',
10691079
'format', 'trigger', 'follow', 'defineProperties', 'textures', 'bumpmaps', 'slice', 'plot',
1070-
'pop', 'pypop', 'insert', 'find', 'extend', 'copy', 'count', 'reverse', 'pysort',
1080+
'pypop', 'insert', 'find', 'extend', 'copy', 'count', 'reverse', 'pysort', 'set',
1081+
'clear', 'copy', 'get', 'items', 'keys', 'values', 'popitem', 'fromkeys', 'update', 'setdefault',
10711082
'npoints', 'unshift', 'splice', 'modify', 'clear', 'shift', 'point', 'slice']
10721083

10731084
// If not a user function, nor pause/waitfor/rate/sleep/read_local_file/get_library,
@@ -1177,10 +1188,11 @@ where compile() was called, in untrusted/run.js.
11771188

11781189
// Delete the string inserts of function-like elements of strings:
11791190
program = program.replace(new RegExp(string_insert, 'g'), '(')
1191+
1192+
let s = "scene = canvas();\n"
1193+
let sc = program.indexOf(s) + s.length
11801194

11811195
if (loadfonts) { // if text object is in user program
1182-
let s = "scene = canvas();\n"
1183-
let sc = program.indexOf(s) + s.length
11841196
s = " fontloading();\n await waitforfonts();\n" // wait for font files
11851197
program = program.slice(0,sc)+s+program.slice(sc,program.length)
11861198
}
@@ -1189,8 +1201,6 @@ where compile() was called, in untrusted/run.js.
11891201
// and it looks like Chrome will also start doing this. So starting with version 3.2, we insert the
11901202
// input function into the user's program:
11911203
if (program.indexOf('input') >= 0) { // if user code invokes input(), insert the function:
1192-
let s = "scene = canvas();\n"
1193-
let sc = program.indexOf(s) + s.length
11941204
s = "\n function input(arg) {\n"
11951205
s += " arg = arg || {}\n"
11961206
s += " if (arg.prompt !== undefined && arg.prompt != '') return prompt(arg.prompt)\n"
@@ -1200,6 +1210,9 @@ where compile() was called, in untrusted/run.js.
12001210
program = program.slice(0,sc)+s+program.slice(sc,program.length)
12011211
}
12021212

1213+
// s = " ρσ_list_decorate.prototype.pop = function(arg) {return this.pypop(arg)}\n"
1214+
// program = program.slice(0,sc)+s+program.slice(sc,program.length)
1215+
12031216
// var p = program.split('\n')
12041217
// for (var i=0; i<p.length; i++) console.log(i, p[i])
12051218
// console.log('fcts', fcts)
@@ -1208,8 +1221,8 @@ where compile() was called, in untrusted/run.js.
12081221
// console.log('classinstances', classinstances)
12091222
// console.log('classmethods', classmethods)
12101223
// console.log('============================================================================')
1211-
// var i = program.search('async function __main__')
12121224
// var i = program.search('"2";')
1225+
// var i = program.search('async function __main__')
12131226
// console.log(program.slice(i))
12141227
// console.log(program)
12151228
return program

lib/glow/api_misc.js

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -134,31 +134,39 @@
134134
}
135135

136136
function convert(arg) {
137+
let s
137138
if (arg instanceof vec) { arg = arg.toString()
138139
} else if (arg === null) { arg = "null"
139140
} else if (arg === undefined) { arg = "undefined"
140141
} else if (toType(arg) == "object") { // object literal; should use recursion. like array.toString() in this file
141-
/* Not using Python dictionaries; too expensive
142-
if (arg.jsmap !== undefined) {
143-
var temp = {}
142+
let zerojsmap = false
143+
if (arg.jsmap !== undefined) { // dictionary
144+
zerojsmap = (arg.jsmap.size == 0)
145+
let temp = {}
144146
for (var [key,value] of arg.jsmap) temp[key] = value
145147
arg = temp
146-
}
147-
*/
148-
var s = "{"
149-
for (var a in arg) s += a + ":" + arg[a] + ", "
150-
arg = s.slice(0,-2) + "}"
148+
if (zerojsmap) arg = "{}"
149+
else {
150+
s = "{"
151+
for (let a in arg) s += a + ":" + arg[a] + ", "
152+
arg = s.slice(0,-2) + "}"
153+
}
154+
}
155+
} else if (toType(arg) == 'map') {
156+
s = 'dict_keys([' // or dict_items or dict_values
157+
for (const k of arg) s += "'"+k + "', "
158+
arg = s.slice(0,-2)+'])'
151159
} else if (toType(arg) == "number") { // poptions.digits default value is 6
152-
var period, char, end
160+
let period, char, end
153161
if (arg === 0) return 0
154-
var d = poptions.digits
155-
var output = []
156-
var val = Math.abs(arg)
162+
let d = poptions.digits
163+
let output = []
164+
let val = Math.abs(arg)
157165
if (val < 1e-2) arg = arg.toExponential(d-1)
158166
else if (val < 1) arg = arg.toPrecision(d)
159167
else if (val >= 1e4) arg = arg.toExponential(d-1)
160168
else { // range from 1 to 10000
161-
var f = 0
169+
let f = 0
162170
if (d == 2 && val < 10) {
163171
f = 1
164172
} else if (d == 3) {
@@ -176,7 +184,7 @@
176184
}
177185
arg = arg.toFixed(f)
178186
}
179-
var period = arg.indexOf('.')
187+
period = arg.indexOf('.')
180188
if (period >= 0) {
181189
end = arg.indexOf('e')
182190
if (end < 0) end = arg.length

lib/glow/canvas.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
this.up = this.up // set up attribute vector
202202
this.__triggered = undefined // set to event by trigger (or null, if waitfor textures)
203203
this.__waitfor_bound = undefined // associated with waitfor and pause
204+
this.__radio_buttons = {}
204205
this.__id = __id
205206
__id++
206207
}

0 commit comments

Comments
 (0)