Skip to content

Commit

Permalink
New PYAIJS and Instructor stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
acbart committed Oct 22, 2017
1 parent 7558c08 commit 1dd0722
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 16 deletions.
7 changes: 5 additions & 2 deletions blockpy_new.html
Expand Up @@ -132,7 +132,9 @@
//'give_feedback': "log(parse_program().find_all('FunctionDef')[0].args.args[0].arg)",
//'give_feedback': 'set_success()',
//'give_feedback': "from instructor_utility import *\nensure_operation('in')",
'give_feedback': 'reset_output()\nqueue_input("Test")\nrun_student()\nlog(get_output())',
//'give_feedback': 'reset_output()\nqueue_input("Test")\nrun_student()\nlog(get_output())',
//'give_feedback': "from instructor_files import *\nfiles_not_handled_correctly('example.txt')",
'give_feedback': "from instructor_imports import *\nensure_imports('math', 'random')",
//'give_feedback': 'ast = parse_program()\nassignments = ast.find_all("Assign")\nfor assignment in assignments:\n if assignment.targets.id == "parking_allowed":\n log(assignment.targets.data_type)',
'on_change': '',
//'on_change': 'gently("Test")',
Expand All @@ -155,7 +157,8 @@
//'__main__': 'round(float("9.5", ___))',
//'__main__': "import matplotlib.pyplot as plt\nplt.scatter([1, 2, 3],[4, 5, 6])\nplt.show()",
//'__main__': "import requests\nprint(requests.get('https://pastebin.com/raw/V7tWn1Rj').text)"
'__main__': "print(open('example.txt').read())"
//'__main__': "print(open('example.txt').read())"
'__main__': "import math\nmath\nfrom random import choice\nchoice"
//'__main__': "from random import randint\nprint(5+randint(1,10))"
//'__main__': 'print(input("Prompt:"))',
//'__main__': 'import parking\nparking_allowed = parking.now()\nif parking.now() > parking.Time(8,30,"AM") and parking.now() < parking.Time(5,30,"PM"):\n parking_allowed = False\nelse:\n parking_allowed = True \nprint(parking_allowed)'
Expand Down
2 changes: 1 addition & 1 deletion makefile
Expand Up @@ -6,4 +6,4 @@ merge:
build:
python build.py
update_kennel:
python merge.py ; cd ../kennel ; py3 manage.py update_blockpy ; cd ../blockpy
python merge.py ; cd ../kennel ; C:/Users/acbart/Anaconda3/python.exe manage.py update_blockpy ; cd ../blockpy
14 changes: 7 additions & 7 deletions skulpt/src/file.js
Expand Up @@ -202,16 +202,16 @@ Sk.builtin.file.prototype["truncate"] = new Sk.builtin.func(function truncate(se
});

Sk.builtin.file.prototype["write"] = new Sk.builtin.func(function write(self, str) {
var mode = Sk.ffi.remapToJs(self.mode);
if (mode === "w" || mode === "wb" || mode === "a" || mode === "ab") {
if (self.fileno === 1) {
Sk.output(Sk.ffi.remapToJs(str));
} else {
goog.asserts.fail();
}
//var mode = Sk.ffi.remapToJs(self.mode);
if (self.fileno === 1) {
Sk.output(Sk.ffi.remapToJs(str));
} else {
goog.asserts.fail();
}
/*if (mode === "w" || mode === "wb" || mode === "a" || mode === "ab") {
} else {
goog.asserts.fail();
}*/
});


Expand Down
3 changes: 1 addition & 2 deletions skulpt/tmp.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions src/abstract_interpreter.js
Expand Up @@ -560,6 +560,31 @@ AbstractInterpreter.prototype.visit_Assign = function(node) {
}

}
AbstractInterpreter.prototype.visit_With = function(node) {
this.visit(node.context_expr);
this.visitList(node.optional_vars);
var typeValue = this.typecheck(node.context_expr),
loc = this.getLocation(node),
that = this;
var recursivelyVisitVars = function(target, currentTypeValue) {
if (target._astname === "Name" && target.ctx.prototype._astname === "Store") {
that.setVariable(target.id.v, currentTypeValue, loc);
} else if (target._astname == 'Tuple' || target._astname == "List") {
for (var i = 0, len = target.elts.length; i < len; i++) {
recursivelyVisitVars(target.elts[i],
that.unpackSequenceType(currentTypeValue, i),
loc);
}
} else {
that.visit(target);
}
}
recursivelyVisitVars(node.optional_vars, typeValue);
// Handle the bodies
for (var i = 0, len = node.body.length; i < len; i++) {
this.visit(node.body[i]);
}
}
AbstractInterpreter.prototype.visit_Import = function(node) {
for (var i = 0, len = node.names.length; i < len; i++) {
var module = node.names[i];
Expand Down
1 change: 1 addition & 0 deletions src/abstract_interpreter_definitions.js
Expand Up @@ -5,6 +5,7 @@ AbstractInterpreter.prototype.TYPE_INHERITANCE = {
AbstractInterpreter.prototype.BUILTINS = {
//
'KeyError': {"type": "Exception"},
'IOError': {"type": "Exception"},
// Values
'True': {"type": "Bool"},
'False': {"type": "Bool"},
Expand Down
3 changes: 3 additions & 0 deletions src/abstract_interpreter_tests.js
Expand Up @@ -129,6 +129,9 @@
// While
['user = input("Give a word.")\nwhile user:\n print(user)\n user = input("Give another word.")',
['Unread variables'], []],

// With
['with open("A") as a:\n print(a)', ['Undefined variables'], []],
];

var errors = 0;
Expand Down
47 changes: 47 additions & 0 deletions src/instructor/instructor_files.py
@@ -0,0 +1,47 @@
from instructor import *
from instructor_utility import *

def files_not_handled_correctly(*filenames):
if filenames and isinstance(filenames[0], int):
num_filenames = filenames[0]
actual_filenames = False
else:
num_filenames = len(filenames)
actual_filenames = True
ast = parse_program()
calls = ast.find_all("Call")
called_open = []
closed = []
for a_call in calls:
if a_call.func.ast_name == 'Name':
if a_call.func.id == 'open':
if not a_call.args:
gently("You have called the <code>open</code> function without any arguments. It needs a filename.")
return True
called_open.append(a_call)
elif a_call.func.id == 'close':
explain("You have attempted to call <code>close</code> as a function, but it is actually a method of the file object.")
return True
elif a_call.func.ast_name == 'Attribute':
if a_call.func.attr == 'open':
gently("You have attempted to call <code>open</code> as a method, but it is actually a built-in function.")
return True
elif a_call.func.attr == 'close':
closed.append(a_call)

if len(called_open) < num_filenames:
gently("You have not opened all the files you were supposed to.")
return True
elif len(called_open) > num_filenames:
gently("You have opened more files than you were supposed to.")
return True
withs = ast.find_all("With")
if len(withs) + len(closed) < num_filenames:
gently("You have not closed all the files you were supposed to.")
return True
elif len(withs) + len(closed) > num_filenames:
gently("You have closed more files than you were supposed to.")
return True
if actual_filenames:
ensure_literal(*filenames)
return False
2 changes: 1 addition & 1 deletion src/instructor/instructor_functions.py
Expand Up @@ -52,4 +52,4 @@ def unit_test(name, *tests):
return None
else:
gently("The function <code>{}</code> was not defined.".format(name))
return None
return None
23 changes: 23 additions & 0 deletions src/instructor/instructor_imports.py
@@ -0,0 +1,23 @@
from instructor import *

def ensure_imports(*modules):
ast = parse_program()
for module in modules:
imports= ast.find_all("Import")
import_froms = ast.find_all("ImportFrom")
if not imports and not import_froms:
gently("You need to import the <code>{}</code> module!".format(module))
return True
success = False
if imports:
if any(alias._name == module
for i in imports
for alias in i.names):
success = True
if import_froms:
if any(i.module == module for i in import_froms):
success = True
if not success:
gently("You need to import the <code>{}</code> module.".format(module))
return True
return False
9 changes: 9 additions & 0 deletions src/instructor/instructor_utility.py
Expand Up @@ -9,6 +9,15 @@ def is_top_level(ast_node):
elif element == ast_node:
return True
return False

def no_nested_function_definitions():
ast = parse_program()
defs = ast.find_all('FunctionDef')
for a_def in defs:
if not is_top_level(a_def):
gently("You have defined a function inside of another block. For instance, you may have placed it inside another function definition, or inside of a loop. Do not nest your function definition!")
return False
return True

def find_function_calls(name):
ast = parse_program()
Expand Down
8 changes: 8 additions & 0 deletions src/interface.html
Expand Up @@ -66,6 +66,12 @@ <h4 class='modal-title'>Dynamic Content</h4>
<!--Disable Semantic Errors: <input type='checkbox' data-bind="checked: settings.disable_semantic_errors"><br>-->

<!--Disable Typed Blocks: <input type='checkbox' data-bind="checked: settings.disable_variable_types"><br>-->
<div class='pull-right'>
<label>AID:</label> <span data-bind="text: assignment.assignment_id"></span>
<label>GID:</label> <span data-bind="text: assignment.group_id"></span>
<label>SID:</label> <span data-bind="text: assignment.student_id"></span>
<label>CID:</label> <span data-bind="text: assignment.course_id"></span>
</div>

<label class='pull-right'>
Disable Timeout: <input type='checkbox' data-bind="checked: settings.disable_timeout"><br>
Expand All @@ -80,6 +86,8 @@ <h4 class='modal-title'>Dynamic Content</h4>
Auto-save:
<input type='checkbox' data-bind="checked:settings.auto_upload"><br>
</label>

<br>
</div>
<!--<img src="images/corgi.png" class='img-responsive' />-->
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/interface.js

Large diffs are not rendered by default.

0 comments on commit 1dd0722

Please sign in to comment.