1
1
mirror of https://github.com/github/semantic.git synced 2024-12-25 07:55:12 +03:00

Merge branch 'master' into test-java-assignment-part-2

This commit is contained in:
Rob Rix 2018-07-26 09:23:09 -04:00 committed by GitHub
commit 05d2683012
146 changed files with 3371 additions and 467 deletions

View File

@ -0,0 +1,18 @@
---
type: cabal
name: type-aligned
version: 0.9.6
summary: Various type-aligned sequence data structures.
homepage: https://github.com/atzeus/type-aligned
license: bsd-3-clause
---
Copyright (c) 2014, Atze van der Ploeg
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the Atze van der Ploeg nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

View File

@ -6,6 +6,9 @@ import "ruby-terms.proto";
import "ruby-diffs.proto";
import "json-terms.proto";
import "typescript-terms.proto";
import "typescript-diffs.proto";
import "python-terms.proto";
import "python-diffs.proto";
import "types.proto";
import "error_details.proto";
@ -48,6 +51,7 @@ message ParseTreeResponse {
RubyResponse ruby = 1;
JSONResponse json = 2;
TypeScriptResponse typescript = 3;
PythonResponse python = 4;
}
}
@ -63,6 +67,10 @@ message TypeScriptResponse {
repeated typescript_terms.TypeScriptTerm terms = 1;
}
message PythonResponse {
repeated python_terms.PythonTerm terms = 1;
}
message SummarizeDiffRequest {
repeated BlobPair blobPairs = 1;
}
@ -79,6 +87,8 @@ message DiffTreeRequest {
message DiffTreeResponse {
oneof response_type {
RubyDiffResponse ruby = 1;
PythonDiffResponse python = 2;
TypeScriptDiffResponse typescript = 3;
}
}
@ -86,6 +96,14 @@ message RubyDiffResponse {
repeated ruby_diffs.RubyDiff diffs = 1;
}
message PythonDiffResponse {
repeated python_diffs.PythonDiff diffs = 1;
}
message TypeScriptDiffResponse {
repeated typescript_diffs.TypeScriptDiff diffs = 1;
}
message CallGraphRequest {
Project project = 1;
}

486
proto/python-diffs.proto Normal file
View File

@ -0,0 +1,486 @@
// This file was generated by proto-gen. Do not edit by hand.
syntax = "proto3";
package github.semantic.python_diffs;
import "types.proto";
option java_package = "com.github.semantic.python_diffs";
option go_package = "github.com/semantic/python_diffs;python";
message PythonDiff {
oneof diff {
Merge merge = 1;
Delete delete = 2;
Insert insert = 3;
Replace replace = 4;
}
message Merge {
PythonSyntax syntax = 1;
}
message Delete {
PythonSyntax before = 1;
}
message Insert {
PythonSyntax after = 1;
}
message Replace {
PythonSyntax before = 1;
PythonSyntax after = 2;
}
}
message QualifiedName {
oneof sum {
QualifiedName qualifiedName = 1;
RelativeQualifiedName relativeQualifiedName = 2;
}
message QualifiedName {
repeated string paths = 1;
}
message RelativeQualifiedName {
string path = 1;
QualifiedName maybeQualifiedName = 2;
}
}
message Alias {
bytes aliasValue = 1;
bytes aliasName = 2;
}
message PythonSyntax {
oneof syntax {
Comment comment = 1;
Class class = 2;
Comprehension comprehension = 3;
Decorator decorator = 4;
Function function = 5;
Variable variable = 6;
Plus plus = 7;
Minus minus = 8;
Times times = 9;
DividedBy dividedBy = 10;
Modulo modulo = 11;
Power power = 12;
Negate negate = 13;
FloorDivision floorDivision = 14;
And and = 15;
Not not = 16;
Or or = 17;
XOr xOr = 18;
BAnd bAnd = 19;
BOr bOr = 20;
BXOr bXOr = 21;
LShift lShift = 22;
RShift rShift = 23;
Complement complement = 24;
Call call = 25;
LessThan lessThan = 26;
LessThanEqual lessThanEqual = 27;
GreaterThan greaterThan = 28;
GreaterThanEqual greaterThanEqual = 29;
Equal equal = 30;
StrictEqual strictEqual = 31;
Comparison comparison = 32;
Enumeration enumeration = 33;
ScopeResolution scopeResolution = 34;
MemberAccess memberAccess = 35;
Subscript subscript = 36;
Member member = 37;
Array array = 38;
Boolean boolean = 39;
Float float = 40;
Hash hash = 41;
Integer integer = 42;
KeyValue keyValue = 43;
Null null = 44;
Set set = 45;
String string = 46;
TextElement textElement = 47;
Tuple tuple = 48;
Redirect redirect = 49;
Assignment assignment = 50;
Break break = 51;
Catch catch = 52;
Continue continue = 53;
Else else = 54;
Finally finally = 55;
ForEach forEach = 56;
If if = 57;
Let let = 58;
NoOp noOp = 59;
Return return = 60;
Statements statements = 61;
Throw throw = 62;
Try try = 63;
While while = 64;
Yield yield = 65;
Ellipsis ellipsis = 66;
Import import = 67;
QualifiedImport qualifiedImport = 68;
QualifiedAliasedImport qualifiedAliasedImport = 69;
Context context = 70;
Empty empty = 71;
Error error = 72;
Identifier identifier = 73;
Annotation annotation = 74;
List list = 75;
}
}
message Comment {
string commentContent = 1;
}
message Class {
repeated PythonDiff classContext = 1;
PythonDiff classIdentifier = 2;
repeated PythonDiff classSuperclasses = 3;
PythonDiff classBody = 4;
}
message Comprehension {
PythonDiff comprehensionValue = 1;
PythonDiff comprehensionBody = 2;
}
message Decorator {
PythonDiff decoratorIdentifier = 1;
repeated PythonDiff decoratorParamaters = 2;
PythonDiff decoratorBody = 3;
}
message Function {
repeated PythonDiff functionContext = 1;
PythonDiff functionName = 2;
repeated PythonDiff functionParameters = 3;
PythonDiff functionBody = 4;
}
message Variable {
PythonDiff variableName = 1;
PythonDiff variableType = 2;
PythonDiff variableValue = 3;
}
message Plus {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Minus {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Times {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message DividedBy {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Modulo {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Power {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Negate {
PythonDiff term = 1;
}
message FloorDivision {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message And {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Not {
PythonDiff term = 1;
}
message Or {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message XOr {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message BAnd {
PythonDiff left = 1;
PythonDiff right = 2;
}
message BOr {
PythonDiff left = 1;
PythonDiff right = 2;
}
message BXOr {
PythonDiff left = 1;
PythonDiff right = 2;
}
message LShift {
PythonDiff left = 1;
PythonDiff right = 2;
}
message RShift {
PythonDiff left = 1;
PythonDiff right = 2;
}
message Complement {
PythonDiff value = 1;
}
message Call {
repeated PythonDiff callContext = 1;
PythonDiff callFunction = 2;
repeated PythonDiff callParams = 3;
PythonDiff callBlock = 4;
}
message LessThan {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message LessThanEqual {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message GreaterThan {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message GreaterThanEqual {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Equal {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message StrictEqual {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Comparison {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Enumeration {
PythonDiff enumerationStart = 1;
PythonDiff enumerationEnd = 2;
PythonDiff enumerationStep = 3;
}
message ScopeResolution {
repeated PythonDiff scopes = 1;
}
message MemberAccess {
PythonDiff lhs = 1;
bytes rhs = 2;
}
message Subscript {
PythonDiff lhs = 1;
repeated PythonDiff rhs = 2;
}
message Member {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Array {
repeated PythonDiff arrayElements = 1;
}
message Boolean {
bool booleanContent = 1;
}
message Float {
string floatContent = 1;
}
message Hash {
repeated PythonDiff hashElements = 1;
}
message Integer {
string integerContent = 1;
}
message KeyValue {
PythonDiff key = 1;
PythonDiff value = 2;
}
message Null { }
message Set {
repeated PythonDiff setElements = 1;
}
message String {
repeated PythonDiff stringElements = 1;
}
message TextElement {
string textElementContent = 1;
}
message Tuple {
repeated PythonDiff tupleContents = 1;
}
message Redirect {
PythonDiff lhs = 1;
PythonDiff rhs = 2;
}
message Assignment {
repeated PythonDiff assignmentContext = 1;
PythonDiff assignmentTarget = 2;
PythonDiff assignmentValue = 3;
}
message Break {
PythonDiff term = 1;
}
message Catch {
PythonDiff catchException = 1;
PythonDiff catchBody = 2;
}
message Continue {
PythonDiff term = 1;
}
message Else {
PythonDiff elseCondition = 1;
PythonDiff elseBody = 2;
}
message Finally {
PythonDiff term = 1;
}
message ForEach {
PythonDiff forEachBinding = 1;
PythonDiff forEachSubject = 2;
PythonDiff forEachBody = 3;
}
message If {
PythonDiff ifCondition = 1;
PythonDiff ifThenBody = 2;
PythonDiff ifElseBody = 3;
}
message Let {
PythonDiff letVariable = 1;
PythonDiff letValue = 2;
PythonDiff letBody = 3;
}
message NoOp {
PythonDiff value = 1;
}
message Return {
PythonDiff term = 1;
}
message Statements {
repeated PythonDiff statements = 1;
}
message Throw {
PythonDiff value = 1;
}
message Try {
PythonDiff tryBody = 1;
repeated PythonDiff tryCatch = 2;
}
message While {
PythonDiff whileCondition = 1;
PythonDiff whileBody = 2;
}
message Yield {
PythonDiff term = 1;
}
message Ellipsis { }
message Import {
QualifiedName importFrom = 1;
repeated Alias importSymbols = 2;
}
message QualifiedImport {
repeated string qualifiedImportFrom = 1;
}
message QualifiedAliasedImport {
QualifiedName qualifiedAliasedImportFrom = 1;
PythonDiff qualifiedAliasedImportAlias = 2;
}
message Context {
repeated PythonDiff contextTerms = 1;
PythonDiff contextSubject = 2;
}
message Empty { }
message Error {
repeated ErrorSite errorCallStack = 1;
repeated string errorExpected = 2;
string errorActual = 3;
repeated PythonDiff errorChildren = 4;
}
message Identifier {
bytes name = 1;
}
message Annotation {
PythonDiff annotationSubject = 1;
PythonDiff annotationType = 2;
}
message List {
repeated PythonDiff listContent = 1;
}

468
proto/python-terms.proto Normal file
View File

@ -0,0 +1,468 @@
// This file was generated by proto-gen. Do not edit by hand.
syntax = "proto3";
package github.semantic.python_terms;
import "types.proto";
option java_package = "com.github.semantic.python_terms";
option go_package = "github.com/semantic/python_terms;python";
message PythonTerm {
PythonSyntax syntax = 1;
}
message QualifiedName {
oneof sum {
QualifiedName qualifiedName = 1;
RelativeQualifiedName relativeQualifiedName = 2;
}
message QualifiedName {
repeated string paths = 1;
}
message RelativeQualifiedName {
string path = 1;
QualifiedName maybeQualifiedName = 2;
}
}
message Alias {
bytes aliasValue = 1;
bytes aliasName = 2;
}
message PythonSyntax {
oneof syntax {
Comment comment = 1;
Class class = 2;
Comprehension comprehension = 3;
Decorator decorator = 4;
Function function = 5;
Variable variable = 6;
Plus plus = 7;
Minus minus = 8;
Times times = 9;
DividedBy dividedBy = 10;
Modulo modulo = 11;
Power power = 12;
Negate negate = 13;
FloorDivision floorDivision = 14;
And and = 15;
Not not = 16;
Or or = 17;
XOr xOr = 18;
BAnd bAnd = 19;
BOr bOr = 20;
BXOr bXOr = 21;
LShift lShift = 22;
RShift rShift = 23;
Complement complement = 24;
Call call = 25;
LessThan lessThan = 26;
LessThanEqual lessThanEqual = 27;
GreaterThan greaterThan = 28;
GreaterThanEqual greaterThanEqual = 29;
Equal equal = 30;
StrictEqual strictEqual = 31;
Comparison comparison = 32;
Enumeration enumeration = 33;
ScopeResolution scopeResolution = 34;
MemberAccess memberAccess = 35;
Subscript subscript = 36;
Member member = 37;
Array array = 38;
Boolean boolean = 39;
Float float = 40;
Hash hash = 41;
Integer integer = 42;
KeyValue keyValue = 43;
Null null = 44;
Set set = 45;
String string = 46;
TextElement textElement = 47;
Tuple tuple = 48;
Redirect redirect = 49;
Assignment assignment = 50;
Break break = 51;
Catch catch = 52;
Continue continue = 53;
Else else = 54;
Finally finally = 55;
ForEach forEach = 56;
If if = 57;
Let let = 58;
NoOp noOp = 59;
Return return = 60;
Statements statements = 61;
Throw throw = 62;
Try try = 63;
While while = 64;
Yield yield = 65;
Ellipsis ellipsis = 66;
Import import = 67;
QualifiedImport qualifiedImport = 68;
QualifiedAliasedImport qualifiedAliasedImport = 69;
Context context = 70;
Empty empty = 71;
Error error = 72;
Identifier identifier = 73;
Annotation annotation = 74;
List list = 75;
}
}
message Comment {
string commentContent = 1;
}
message Class {
repeated PythonTerm classContext = 1;
PythonTerm classIdentifier = 2;
repeated PythonTerm classSuperclasses = 3;
PythonTerm classBody = 4;
}
message Comprehension {
PythonTerm comprehensionValue = 1;
PythonTerm comprehensionBody = 2;
}
message Decorator {
PythonTerm decoratorIdentifier = 1;
repeated PythonTerm decoratorParamaters = 2;
PythonTerm decoratorBody = 3;
}
message Function {
repeated PythonTerm functionContext = 1;
PythonTerm functionName = 2;
repeated PythonTerm functionParameters = 3;
PythonTerm functionBody = 4;
}
message Variable {
PythonTerm variableName = 1;
PythonTerm variableType = 2;
PythonTerm variableValue = 3;
}
message Plus {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Minus {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Times {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message DividedBy {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Modulo {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Power {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Negate {
PythonTerm term = 1;
}
message FloorDivision {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message And {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Not {
PythonTerm term = 1;
}
message Or {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message XOr {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message BAnd {
PythonTerm left = 1;
PythonTerm right = 2;
}
message BOr {
PythonTerm left = 1;
PythonTerm right = 2;
}
message BXOr {
PythonTerm left = 1;
PythonTerm right = 2;
}
message LShift {
PythonTerm left = 1;
PythonTerm right = 2;
}
message RShift {
PythonTerm left = 1;
PythonTerm right = 2;
}
message Complement {
PythonTerm value = 1;
}
message Call {
repeated PythonTerm callContext = 1;
PythonTerm callFunction = 2;
repeated PythonTerm callParams = 3;
PythonTerm callBlock = 4;
}
message LessThan {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message LessThanEqual {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message GreaterThan {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message GreaterThanEqual {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Equal {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message StrictEqual {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Comparison {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Enumeration {
PythonTerm enumerationStart = 1;
PythonTerm enumerationEnd = 2;
PythonTerm enumerationStep = 3;
}
message ScopeResolution {
repeated PythonTerm scopes = 1;
}
message MemberAccess {
PythonTerm lhs = 1;
bytes rhs = 2;
}
message Subscript {
PythonTerm lhs = 1;
repeated PythonTerm rhs = 2;
}
message Member {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Array {
repeated PythonTerm arrayElements = 1;
}
message Boolean {
bool booleanContent = 1;
}
message Float {
string floatContent = 1;
}
message Hash {
repeated PythonTerm hashElements = 1;
}
message Integer {
string integerContent = 1;
}
message KeyValue {
PythonTerm key = 1;
PythonTerm value = 2;
}
message Null { }
message Set {
repeated PythonTerm setElements = 1;
}
message String {
repeated PythonTerm stringElements = 1;
}
message TextElement {
string textElementContent = 1;
}
message Tuple {
repeated PythonTerm tupleContents = 1;
}
message Redirect {
PythonTerm lhs = 1;
PythonTerm rhs = 2;
}
message Assignment {
repeated PythonTerm assignmentContext = 1;
PythonTerm assignmentTarget = 2;
PythonTerm assignmentValue = 3;
}
message Break {
PythonTerm term = 1;
}
message Catch {
PythonTerm catchException = 1;
PythonTerm catchBody = 2;
}
message Continue {
PythonTerm term = 1;
}
message Else {
PythonTerm elseCondition = 1;
PythonTerm elseBody = 2;
}
message Finally {
PythonTerm term = 1;
}
message ForEach {
PythonTerm forEachBinding = 1;
PythonTerm forEachSubject = 2;
PythonTerm forEachBody = 3;
}
message If {
PythonTerm ifCondition = 1;
PythonTerm ifThenBody = 2;
PythonTerm ifElseBody = 3;
}
message Let {
PythonTerm letVariable = 1;
PythonTerm letValue = 2;
PythonTerm letBody = 3;
}
message NoOp {
PythonTerm value = 1;
}
message Return {
PythonTerm term = 1;
}
message Statements {
repeated PythonTerm statements = 1;
}
message Throw {
PythonTerm value = 1;
}
message Try {
PythonTerm tryBody = 1;
repeated PythonTerm tryCatch = 2;
}
message While {
PythonTerm whileCondition = 1;
PythonTerm whileBody = 2;
}
message Yield {
PythonTerm term = 1;
}
message Ellipsis { }
message Import {
QualifiedName importFrom = 1;
repeated Alias importSymbols = 2;
}
message QualifiedImport {
repeated string qualifiedImportFrom = 1;
}
message QualifiedAliasedImport {
QualifiedName qualifiedAliasedImportFrom = 1;
PythonTerm qualifiedAliasedImportAlias = 2;
}
message Context {
repeated PythonTerm contextTerms = 1;
PythonTerm contextSubject = 2;
}
message Empty { }
message Error {
repeated ErrorSite errorCallStack = 1;
repeated string errorExpected = 2;
string errorActual = 3;
repeated PythonTerm errorChildren = 4;
}
message Identifier {
bytes name = 1;
}
message Annotation {
PythonTerm annotationSubject = 1;
PythonTerm annotationType = 2;
}
message List {
repeated PythonTerm listContent = 1;
}

View File

@ -25,6 +25,8 @@ enum VertexType {
PACKAGE = 0;
MODULE = 1;
VARIABLE = 2;
METHOD = 3;
FUNCTION = 4;
}
message BlobPair {

View File

@ -0,0 +1,981 @@
// This file was generated by proto-gen. Do not edit by hand.
syntax = "proto3";
package github.semantic.typescript_diffs;
import "types.proto";
option java_package = "com.github.semantic.typescript_diffs";
option go_package = "github.com/semantic/typescript_diffs;typescript";
message TypeScriptDiff {
oneof diff {
Merge merge = 1;
Delete delete = 2;
Insert insert = 3;
Replace replace = 4;
}
message Merge {
TypeScriptSyntax syntax = 1;
}
message Delete {
TypeScriptSyntax before = 1;
}
message Insert {
TypeScriptSyntax after = 1;
}
message Replace {
TypeScriptSyntax before = 1;
TypeScriptSyntax after = 2;
}
}
message Alias {
bytes aliasValue = 1;
bytes aliasName = 2;
}
message ImportPath {
string unPath = 1;
IsRelative pathIsRelative = 2;
}
enum IsRelative {
Unknown = 0;
Relative = 1;
NonRelative = 2;
}
message TypeScriptSyntax {
oneof syntax {
Comment comment = 1;
HashBang hashBang = 2;
Class class = 3;
Function function = 4;
Method method = 5;
MethodSignature methodSignature = 6;
InterfaceDeclaration interfaceDeclaration = 7;
PublicFieldDefinition publicFieldDefinition = 8;
VariableDeclaration variableDeclaration = 9;
TypeAlias typeAlias = 10;
Plus plus = 11;
Minus minus = 12;
Times times = 13;
DividedBy dividedBy = 14;
Modulo modulo = 15;
Power power = 16;
Negate negate = 17;
FloorDivision floorDivision = 18;
BAnd bAnd = 19;
BOr bOr = 20;
BXOr bXOr = 21;
LShift lShift = 22;
RShift rShift = 23;
UnsignedRShift unsignedRShift = 24;
Complement complement = 25;
And and = 26;
Not not = 27;
Or or = 28;
XOr xOr = 29;
Call call = 30;
Cast cast = 31;
LessThan lessThan = 32;
LessThanEqual lessThanEqual = 33;
GreaterThan greaterThan = 34;
GreaterThanEqual greaterThanEqual = 35;
Equal equal = 36;
StrictEqual strictEqual = 37;
Comparison comparison = 38;
Enumeration enumeration = 39;
MemberAccess memberAccess = 40;
NonNullExpression nonNullExpression = 41;
ScopeResolution scopeResolution = 42;
SequenceExpression sequenceExpression = 43;
Subscript subscript = 44;
Member member = 45;
Delete delete = 46;
Void void = 47;
Typeof typeof = 48;
InstanceOf instanceOf = 49;
New new = 50;
Await await = 51;
Array array = 52;
Boolean boolean = 53;
Float float = 54;
Hash hash = 55;
Integer integer = 56;
KeyValue keyValue = 57;
Null null = 58;
String string = 59;
TextElement textElement = 60;
Regex regex = 61;
Assignment assignment = 62;
Break break = 63;
Catch catch = 64;
Continue continue = 65;
DoWhile doWhile = 66;
Else else = 67;
Finally finally = 68;
For for = 69;
ForEach forEach = 70;
If if = 71;
Match match = 72;
Pattern pattern = 73;
Retry retry = 74;
Return return = 75;
ScopeEntry scopeEntry = 76;
ScopeExit scopeExit = 77;
Statements statements = 78;
Throw throw = 79;
Try try = 80;
While while = 81;
Yield yield = 82;
AccessibilityModifier accessibilityModifier = 83;
Empty empty = 84;
Error error = 85;
Identifier identifier = 86;
Context context = 87;
Readonly readonly = 88;
TypeParameters typeParameters = 89;
TypeParameter typeParameter = 90;
Constraint constraint = 91;
ParenthesizedType parenthesizedType = 92;
DefaultType defaultType = 93;
PredefinedType predefinedType = 94;
TypeIdentifier typeIdentifier = 95;
NestedIdentifier nestedIdentifier = 96;
NestedTypeIdentifier nestedTypeIdentifier = 97;
GenericType genericType = 98;
TypeArguments typeArguments = 99;
TypePredicate typePredicate = 100;
CallSignature callSignature = 101;
ConstructSignature constructSignature = 102;
ArrayType arrayType = 103;
LookupType lookupType = 104;
FlowMaybeType flowMaybeType = 105;
TypeQuery typeQuery = 106;
IndexTypeQuery indexTypeQuery = 107;
ThisType thisType = 108;
ExistentialType existentialType = 109;
AbstractMethodSignature abstractMethodSignature = 110;
IndexSignature indexSignature = 111;
ObjectType objectType = 112;
LiteralType literalType = 113;
Union union = 114;
Intersection intersection = 115;
Module module = 116;
InternalModule internalModule = 117;
FunctionType functionType = 118;
Tuple tuple = 119;
Constructor constructor = 120;
TypeAssertion typeAssertion = 121;
ImportAlias importAlias = 122;
Debugger debugger = 123;
ShorthandPropertyIdentifier shorthandPropertyIdentifier = 124;
Super super = 125;
Undefined undefined = 126;
ClassHeritage classHeritage = 127;
AbstractClass abstractClass = 128;
ImplementsClause implementsClause = 129;
JsxElement jsxElement = 130;
JsxSelfClosingElement jsxSelfClosingElement = 131;
JsxOpeningElement jsxOpeningElement = 132;
JsxText jsxText = 133;
JsxClosingElement jsxClosingElement = 134;
JsxExpression jsxExpression = 135;
JsxAttribute jsxAttribute = 136;
JsxFragment jsxFragment = 137;
JsxNamespaceName jsxNamespaceName = 138;
OptionalParameter optionalParameter = 139;
RequiredParameter requiredParameter = 140;
RestParameter restParameter = 141;
PropertySignature propertySignature = 142;
AmbientDeclaration ambientDeclaration = 143;
EnumDeclaration enumDeclaration = 144;
ExtendsClause extendsClause = 145;
AmbientFunction ambientFunction = 146;
ImportRequireClause importRequireClause = 147;
ImportClause importClause = 148;
LabeledStatement labeledStatement = 149;
Annotation annotation = 150;
With with = 151;
ForOf forOf = 152;
This this = 153;
Update update = 154;
ComputedPropertyName computedPropertyName = 155;
Decorator decorator = 156;
Import import = 157;
QualifiedAliasedImport qualifiedAliasedImport = 158;
SideEffectImport sideEffectImport = 159;
DefaultExport defaultExport = 160;
QualifiedExport qualifiedExport = 161;
QualifiedExportFrom qualifiedExportFrom = 162;
JavaScriptRequire javaScriptRequire = 163;
List list = 164;
}
}
message Comment {
string commentContent = 1;
}
message HashBang {
string value = 1;
}
message Class {
repeated TypeScriptDiff classContext = 1;
TypeScriptDiff classIdentifier = 2;
repeated TypeScriptDiff classSuperclasses = 3;
TypeScriptDiff classBody = 4;
}
message Function {
repeated TypeScriptDiff functionContext = 1;
TypeScriptDiff functionName = 2;
repeated TypeScriptDiff functionParameters = 3;
TypeScriptDiff functionBody = 4;
}
message Method {
repeated TypeScriptDiff methodContext = 1;
TypeScriptDiff methodReceiver = 2;
TypeScriptDiff methodName = 3;
repeated TypeScriptDiff methodParameters = 4;
TypeScriptDiff methodBody = 5;
}
message MethodSignature {
repeated TypeScriptDiff methodSignatureContext = 1;
TypeScriptDiff methodSignatureName = 2;
repeated TypeScriptDiff methodSignatureParameters = 3;
}
message InterfaceDeclaration {
repeated TypeScriptDiff interfaceDeclarationContext = 1;
TypeScriptDiff interfaceDeclarationIdentifier = 2;
TypeScriptDiff interfaceDeclarationBody = 3;
}
message PublicFieldDefinition {
repeated TypeScriptDiff publicFieldContext = 1;
TypeScriptDiff publicFieldPropertyName = 2;
TypeScriptDiff publicFieldValue = 3;
}
message VariableDeclaration {
repeated TypeScriptDiff variableDeclarations = 1;
}
message TypeAlias {
repeated TypeScriptDiff typeAliasContext = 1;
TypeScriptDiff typeAliasIdentifier = 2;
TypeScriptDiff typeAliasKind = 3;
}
message Plus {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Minus {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Times {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message DividedBy {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Modulo {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Power {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Negate {
TypeScriptDiff term = 1;
}
message FloorDivision {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message BAnd {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message BOr {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message BXOr {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message LShift {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message RShift {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message UnsignedRShift {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message Complement {
TypeScriptDiff value = 1;
}
message And {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Not {
TypeScriptDiff term = 1;
}
message Or {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message XOr {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Call {
repeated TypeScriptDiff callContext = 1;
TypeScriptDiff callFunction = 2;
repeated TypeScriptDiff callParams = 3;
TypeScriptDiff callBlock = 4;
}
message Cast {
TypeScriptDiff castSubject = 1;
TypeScriptDiff castType = 2;
}
message LessThan {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message LessThanEqual {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message GreaterThan {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message GreaterThanEqual {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Equal {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message StrictEqual {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Comparison {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Enumeration {
TypeScriptDiff enumerationStart = 1;
TypeScriptDiff enumerationEnd = 2;
TypeScriptDiff enumerationStep = 3;
}
message MemberAccess {
TypeScriptDiff lhs = 1;
bytes rhs = 2;
}
message NonNullExpression {
TypeScriptDiff nonNullExpression = 1;
}
message ScopeResolution {
repeated TypeScriptDiff scopes = 1;
}
message SequenceExpression {
TypeScriptDiff firstExpression = 1;
TypeScriptDiff secondExpression = 2;
}
message Subscript {
TypeScriptDiff lhs = 1;
repeated TypeScriptDiff rhs = 2;
}
message Member {
TypeScriptDiff lhs = 1;
TypeScriptDiff rhs = 2;
}
message Delete {
TypeScriptDiff value = 1;
}
message Void {
TypeScriptDiff value = 1;
}
message Typeof {
TypeScriptDiff value = 1;
}
message InstanceOf {
TypeScriptDiff instanceOfSubject = 1;
TypeScriptDiff instanceOfObject = 2;
}
message New {
repeated TypeScriptDiff newSubject = 1;
}
message Await {
TypeScriptDiff awaitSubject = 1;
}
message Array {
repeated TypeScriptDiff arrayElements = 1;
}
message Boolean {
bool booleanContent = 1;
}
message Float {
string floatContent = 1;
}
message Hash {
repeated TypeScriptDiff hashElements = 1;
}
message Integer {
string integerContent = 1;
}
message KeyValue {
TypeScriptDiff key = 1;
TypeScriptDiff value = 2;
}
message Null { }
message String {
repeated TypeScriptDiff stringElements = 1;
}
message TextElement {
string textElementContent = 1;
}
message Regex {
string regexContent = 1;
}
message Assignment {
repeated TypeScriptDiff assignmentContext = 1;
TypeScriptDiff assignmentTarget = 2;
TypeScriptDiff assignmentValue = 3;
}
message Break {
TypeScriptDiff term = 1;
}
message Catch {
TypeScriptDiff catchException = 1;
TypeScriptDiff catchBody = 2;
}
message Continue {
TypeScriptDiff term = 1;
}
message DoWhile {
TypeScriptDiff doWhileCondition = 1;
TypeScriptDiff doWhileBody = 2;
}
message Else {
TypeScriptDiff elseCondition = 1;
TypeScriptDiff elseBody = 2;
}
message Finally {
TypeScriptDiff term = 1;
}
message For {
TypeScriptDiff forBefore = 1;
TypeScriptDiff forCondition = 2;
TypeScriptDiff forStep = 3;
TypeScriptDiff forBody = 4;
}
message ForEach {
TypeScriptDiff forEachBinding = 1;
TypeScriptDiff forEachSubject = 2;
TypeScriptDiff forEachBody = 3;
}
message If {
TypeScriptDiff ifCondition = 1;
TypeScriptDiff ifThenBody = 2;
TypeScriptDiff ifElseBody = 3;
}
message Match {
TypeScriptDiff matchSubject = 1;
TypeScriptDiff matchPatterns = 2;
}
message Pattern {
TypeScriptDiff value = 1;
TypeScriptDiff patternBody = 2;
}
message Retry {
TypeScriptDiff term = 1;
}
message Return {
TypeScriptDiff term = 1;
}
message ScopeEntry {
repeated TypeScriptDiff terms = 1;
}
message ScopeExit {
repeated TypeScriptDiff terms = 1;
}
message Statements {
repeated TypeScriptDiff statements = 1;
}
message Throw {
TypeScriptDiff value = 1;
}
message Try {
TypeScriptDiff tryBody = 1;
repeated TypeScriptDiff tryCatch = 2;
}
message While {
TypeScriptDiff whileCondition = 1;
TypeScriptDiff whileBody = 2;
}
message Yield {
TypeScriptDiff term = 1;
}
message AccessibilityModifier {
string contents = 1;
}
message Empty { }
message Error {
repeated ErrorSite errorCallStack = 1;
repeated string errorExpected = 2;
string errorActual = 3;
repeated TypeScriptDiff errorChildren = 4;
}
message Identifier {
bytes name = 1;
}
message Context {
repeated TypeScriptDiff contextTerms = 1;
TypeScriptDiff contextSubject = 2;
}
message Readonly { }
message TypeParameters {
repeated TypeScriptDiff terms = 1;
}
message TypeParameter {
TypeScriptDiff typeParameter = 1;
TypeScriptDiff typeParameterConstraint = 2;
TypeScriptDiff typeParameterDefaultType = 3;
}
message Constraint {
TypeScriptDiff constraintType = 1;
}
message ParenthesizedType {
TypeScriptDiff parenthesizedType = 1;
}
message DefaultType {
TypeScriptDiff defaultType = 1;
}
message PredefinedType {
string predefinedType = 1;
}
message TypeIdentifier {
string contents = 1;
}
message NestedIdentifier {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message NestedTypeIdentifier {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message GenericType {
TypeScriptDiff genericTypeIdentifier = 1;
TypeScriptDiff genericTypeArguments = 2;
}
message TypeArguments {
repeated TypeScriptDiff typeArguments = 1;
}
message TypePredicate {
TypeScriptDiff typePredicateIdentifier = 1;
TypeScriptDiff typePredicateType = 2;
}
message CallSignature {
TypeScriptDiff callSignatureTypeParameters = 1;
repeated TypeScriptDiff callSignatureParameters = 2;
TypeScriptDiff callSignatureType = 3;
}
message ConstructSignature {
TypeScriptDiff constructSignatureTypeParameters = 1;
repeated TypeScriptDiff constructSignatureParameters = 2;
TypeScriptDiff constructSignatureType = 3;
}
message ArrayType {
TypeScriptDiff arrayType = 1;
}
message LookupType {
TypeScriptDiff lookupTypeIdentifier = 1;
TypeScriptDiff lookupTypeKey = 2;
}
message FlowMaybeType {
TypeScriptDiff flowMaybeType = 1;
}
message TypeQuery {
TypeScriptDiff typeQuerySubject = 1;
}
message IndexTypeQuery {
TypeScriptDiff indexTypeQuerySubject = 1;
}
message ThisType {
string contents = 1;
}
message ExistentialType {
string contents = 1;
}
message AbstractMethodSignature {
repeated TypeScriptDiff abstractMethodSignatureContext = 1;
TypeScriptDiff abstractMethodSignatureName = 2;
repeated TypeScriptDiff abstractMethodSignatureParameters = 3;
}
message IndexSignature {
TypeScriptDiff indexSignatureSubject = 1;
TypeScriptDiff indexSignatureType = 2;
}
message ObjectType {
repeated TypeScriptDiff objectTypeElements = 1;
}
message LiteralType {
TypeScriptDiff literalTypeSubject = 1;
}
message Union {
TypeScriptDiff unionLeft = 1;
TypeScriptDiff unionRight = 2;
}
message Intersection {
TypeScriptDiff intersectionLeft = 1;
TypeScriptDiff intersectionRight = 2;
}
message Module {
TypeScriptDiff moduleIdentifier = 1;
repeated TypeScriptDiff moduleStatements = 2;
}
message InternalModule {
TypeScriptDiff internalModuleIdentifier = 1;
repeated TypeScriptDiff internalModuleStatements = 2;
}
message FunctionType {
TypeScriptDiff functionTypeParameters = 1;
repeated TypeScriptDiff functionFormalParameters = 2;
TypeScriptDiff functionType = 3;
}
message Tuple {
repeated TypeScriptDiff tupleElements = 1;
}
message Constructor {
TypeScriptDiff constructorTypeParameters = 1;
repeated TypeScriptDiff constructorFormalParameters = 2;
TypeScriptDiff constructorType = 3;
}
message TypeAssertion {
TypeScriptDiff typeAssertionParameters = 1;
TypeScriptDiff typeAssertionExpression = 2;
}
message ImportAlias {
TypeScriptDiff importAliasSubject = 1;
TypeScriptDiff importAlias = 2;
}
message Debugger { }
message ShorthandPropertyIdentifier {
string contents = 1;
}
message Super { }
message Undefined { }
message ClassHeritage {
TypeScriptDiff classHeritageExtendsClause = 1;
TypeScriptDiff implementsClause = 2;
}
message AbstractClass {
TypeScriptDiff abstractClassIdentifier = 1;
TypeScriptDiff abstractClassTypeParameters = 2;
repeated TypeScriptDiff classHeritage = 3;
TypeScriptDiff classBody = 4;
}
message ExtendsClause {
repeated TypeScriptDiff extendsClauses = 1;
}
message ImplementsClause {
repeated TypeScriptDiff implementsClauseTypes = 1;
}
message JsxElement {
TypeScriptDiff jsxOpeningElement = 1;
repeated TypeScriptDiff jsxElements = 2;
TypeScriptDiff jsxClosingElement = 3;
}
message JsxSelfClosingElement {
TypeScriptDiff jsxSelfClosingElementIdentifier = 1;
repeated TypeScriptDiff jsxSelfClosingElementAttributes = 2;
}
message JsxOpeningElement {
TypeScriptDiff jsxOpeningElementIdentifier = 1;
repeated TypeScriptDiff jsxAttributes = 2;
}
message JsxText {
string contents = 1;
}
message JsxClosingElement {
TypeScriptDiff jsxClosingElementIdentifier = 1;
}
message JsxExpression {
TypeScriptDiff jsxExpression = 1;
}
message JsxAttribute {
TypeScriptDiff jsxAttributeTarget = 1;
TypeScriptDiff jsxAttributeValue = 2;
}
message JsxFragment {
repeated TypeScriptDiff terms = 1;
}
message JsxNamespaceName {
TypeScriptDiff left = 1;
TypeScriptDiff right = 2;
}
message OptionalParameter {
repeated TypeScriptDiff optionalParameterContext = 1;
TypeScriptDiff optionalParameterSubject = 2;
}
message RequiredParameter {
repeated TypeScriptDiff requiredParameterContext = 1;
TypeScriptDiff requiredParameterSubject = 2;
}
message RestParameter {
repeated TypeScriptDiff restParameterContext = 1;
TypeScriptDiff restParameterSubject = 2;
}
message PropertySignature {
repeated TypeScriptDiff modifiers = 1;
TypeScriptDiff propertySignaturePropertyName = 2;
}
message AmbientDeclaration {
TypeScriptDiff ambientDeclarationBody = 1;
}
message EnumDeclaration {
TypeScriptDiff enumDeclarationIdentifier = 1;
repeated TypeScriptDiff enumDeclarationBody = 2;
}
message AmbientFunction {
repeated TypeScriptDiff ambientFunctionContext = 1;
TypeScriptDiff ambientFunctionIdentifier = 2;
repeated TypeScriptDiff ambientFunctionParameters = 3;
}
message ImportRequireClause {
TypeScriptDiff importRequireIdentifier = 1;
TypeScriptDiff importRequireSubject = 2;
}
message ImportClause {
repeated TypeScriptDiff importClauseElements = 1;
}
message LabeledStatement {
TypeScriptDiff labeledStatementIdentifier = 1;
TypeScriptDiff labeledStatementSubject = 2;
}
message Annotation {
TypeScriptDiff annotationType = 1;
}
message With {
TypeScriptDiff withExpression = 1;
TypeScriptDiff withBody = 2;
}
message ForOf {
TypeScriptDiff forOfBinding = 1;
TypeScriptDiff forOfSubject = 2;
TypeScriptDiff forOfBody = 3;
}
message This { }
message Update {
TypeScriptDiff updateSubject = 1;
}
message ComputedPropertyName {
TypeScriptDiff propertyName = 1;
}
message Decorator {
TypeScriptDiff decoratorTerm = 1;
}
message Import {
repeated Alias importSymbols = 1;
ImportPath importFrom = 2;
}
message QualifiedAliasedImport {
TypeScriptDiff qualifiedAliasedImportAlias = 1;
ImportPath qualifiedAliasedImportFrom = 2;
}
message SideEffectImport {
ImportPath sideEffectImportFrom = 1;
}
message DefaultExport {
TypeScriptDiff defaultExport = 1;
}
message QualifiedExport {
repeated Alias qualifiedExportSymbols = 1;
}
message QualifiedExportFrom {
ImportPath qualifiedExportFrom = 1;
repeated Alias qualifiedExportFromSymbols = 2;
}
message JavaScriptRequire {
TypeScriptDiff javascriptRequireIden = 1;
ImportPath javascriptRequireFrom = 2;
}
message List {
repeated TypeScriptDiff listContent = 1;
}

View File

@ -21,5 +21,5 @@ collectingTerms recur term = do
v <$ TermEvaluator (gc (roots <> valueRoots v))
providingLiveSet :: (Effectful (m address value), Effects effects) => m address value (Reader (Live address) ': effects) a -> m address value effects a
providingLiveSet :: (Effectful (m address value), PureEffects effects) => m address value (Reader (Live address) ': effects) a -> m address value effects a
providingLiveSet = runReader lowerBound

View File

@ -3,6 +3,7 @@ module Analysis.Abstract.Graph
( Graph(..)
, Vertex(..)
, moduleVertex
, unknownModuleVertex
, style
, appendGraph
, variableDefinition
@ -18,6 +19,7 @@ module Analysis.Abstract.Graph
import Algebra.Graph.Export.Dot hiding (vertexName)
import Control.Abstract
import Data.Abstract.Address
import Data.Abstract.Ref
import Data.Abstract.Declarations
import Data.Abstract.Module (Module (moduleInfo), ModuleInfo (..))
import Data.Abstract.Package (PackageInfo (..))
@ -26,21 +28,24 @@ import Data.Graph
import Data.Graph.Vertex
import Data.Record
import Data.Term
import qualified Data.Map as Map
import qualified Data.Text.Encoding as T
import Prologue hiding (project)
style :: Style Vertex Builder
style = (defaultStyle (T.encodeUtf8Builder . vertexName))
style = (defaultStyle (T.encodeUtf8Builder . vertexIdentifier))
{ vertexAttributes = vertexAttributes
, edgeAttributes = edgeAttributes
}
where vertexAttributes Package{} = [ "style" := "dashed", "shape" := "box" ]
vertexAttributes Module{} = [ "style" := "dotted, rounded", "shape" := "box" ]
vertexAttributes Variable{..} = [ "tooltip" := T.encodeUtf8Builder (showSpan variableSpan), "style" := "rounded", "shape" := "box" ]
vertexAttributes Method{..} = [ "tooltip" := T.encodeUtf8Builder (showSpan methodSpan) , "style" := "rounded", "shape" := "box" ]
vertexAttributes Function{..} = [ "tooltip" := T.encodeUtf8Builder (showSpan functionSpan), "style" := "rounded", "shape" := "box" ]
where vertexAttributes Package{} = [ "style" := "dashed", "shape" := "box" ]
vertexAttributes Module{} = [ "style" := "dotted, rounded", "shape" := "box" ]
vertexAttributes UnknownModule{} = [ "style" := "dotted, rounded", "shape" := "box", "color" := "red", "fontcolor" := "red" ]
vertexAttributes Variable{..} = [ "label" := T.encodeUtf8Builder (vertexName <> " (Variable)"), "tooltip" := T.encodeUtf8Builder (showSpan vertexSpan), "style" := "rounded", "shape" := "box" ]
vertexAttributes Method{..} = [ "label" := T.encodeUtf8Builder (vertexName <> " (Method)"), "tooltip" := T.encodeUtf8Builder (showSpan vertexSpan) , "style" := "rounded", "shape" := "box" ]
vertexAttributes Function{..} = [ "label" := T.encodeUtf8Builder (vertexName <> " (Function)"), "tooltip" := T.encodeUtf8Builder (showSpan vertexSpan), "style" := "rounded", "shape" := "box" ]
edgeAttributes Module{} Module{} = [ "len" := "5.0", "label" := "imports" ]
edgeAttributes Module{} UnknownModule{} = [ "len" := "5.0", "label" := "imports" ]
edgeAttributes Package{} Module{} = [ "len" := "5.0", "style" := "dashed" ]
edgeAttributes Module{} Module{} = [ "len" := "5.0", "label" := "imports" ]
edgeAttributes Variable{} Module{} = [ "len" := "5.0", "color" := "blue", "label" := "refers to symbol defined in" ]
edgeAttributes _ Module{} = [ "len" := "5.0", "color" := "blue", "label" := "defined in" ]
edgeAttributes Method{} Variable{} = [ "len" := "2.0", "color" := "green", "label" := "calls" ]
@ -48,6 +53,8 @@ style = (defaultStyle (T.encodeUtf8Builder . vertexName))
edgeAttributes Module{} Function{} = [ "len" := "2.0", "color" := "red", "label" := "defines" ]
edgeAttributes Module{} Method{} = [ "len" := "2.0", "color" := "red", "label" := "defines" ]
edgeAttributes Module{} _ = [ "len" := "2.0", "color" := "green", "label" := "calls" ]
edgeAttributes Variable{} Function{} = [ "len" := "2.0", "color" := "blue", "label" := "references" ]
edgeAttributes Variable{} Method{} = [ "len" := "2.0", "color" := "blue", "label" := "references" ]
edgeAttributes _ _ = []
@ -55,31 +62,45 @@ style = (defaultStyle (T.encodeUtf8Builder . vertexName))
graphingTerms :: ( Member (Reader ModuleInfo) effects
, Member (Env (Hole context (Located address))) effects
, Member (State (Graph Vertex)) effects
, Member (State (Map (Hole context (Located address)) Vertex)) effects
, Member (Resumable (EnvironmentError (Hole context (Located address)))) effects
, AbstractValue (Hole context (Located address)) value effects
, Member (Reader Vertex) effects
, HasField fields Span
, VertexDeclaration syntax
, Declarations1 syntax
, Ord address
, Ord context
, Foldable syntax
, Functor syntax
, term ~ Term syntax (Record fields)
)
=> SubtermAlgebra (Base term) term (TermEvaluator term (Hole context (Located address)) value effects a)
-> SubtermAlgebra (Base term) term (TermEvaluator term (Hole context (Located address)) value effects a)
=> SubtermAlgebra (Base term) term (TermEvaluator term (Hole context (Located address)) value effects (ValueRef (Hole context (Located address))))
-> SubtermAlgebra (Base term) term (TermEvaluator term (Hole context (Located address)) value effects (ValueRef (Hole context (Located address))))
graphingTerms recur term@(In a syntax) = do
definedInModule <- currentModule
case toVertex a definedInModule (subterm <$> syntax) of
Just (v@Function{}, _) -> recurWithContext v
Just (v@Method{}, _) -> recurWithContext v
Just (Variable{..}, name) -> do
definedInModuleInfo <- maybe (ModuleInfo "unknown") (maybe (ModuleInfo "hole") addressModule . toMaybe) <$> TermEvaluator (lookupEnv name)
variableDefinition (variableVertex variableName definedInModuleInfo variableSpan)
Just (v@Variable{..}, name) -> do
variableDefinition v
maybeAddr <- TermEvaluator (lookupEnv name)
case maybeAddr of
Just a -> do
defined <- gets (Map.lookup a)
maybe (pure ()) (appendGraph . connect (vertex v) . vertex) defined
_ -> pure ()
recur term
_ -> recur term
where
recurWithContext v = do
variableDefinition v
moduleInclusion v
local (const v) (recur term)
local (const v) $ do
valRef <- recur term
addr <- TermEvaluator (Control.Abstract.address valRef)
modify' (Map.insert addr v)
pure valRef
-- | Add vertices to the graph for evaluated modules and the packages containing them.
graphingPackages :: ( Member (Reader PackageInfo) effects
@ -93,11 +114,11 @@ graphingPackages recur m =
-- | Add vertices to the graph for imported modules.
graphingModules :: forall term address value effects a
. ( Effects effects
, Member (Modules address) effects
. ( Member (Modules address) effects
, Member (Reader ModuleInfo) effects
, Member (State (Graph Vertex)) effects
, Member (Reader Vertex) effects
, Member (Reader Vertex) effects
, PureEffects effects
)
=> SubtermAlgebra Module term (TermEvaluator term address value effects a)
-> SubtermAlgebra Module term (TermEvaluator term address value effects a)
@ -106,18 +127,21 @@ graphingModules recur m = do
appendGraph (vertex v)
local (const v) $
eavesdrop @(Modules address) (\ m -> case m of
-- NB: path is null for Languages like Ruby that have module imports that require concrete value semantics.
Load path | not (Prologue.null path) -> moduleInclusion (moduleVertex (ModuleInfo path))
Lookup path | not (Prologue.null path) -> moduleInclusion (moduleVertex (ModuleInfo path))
Load path -> includeModule path
Lookup path -> includeModule path
_ -> pure ())
(recur m)
where
-- NB: path is null for Languages like Ruby that have module imports that require concrete value semantics.
includeModule path = let path' = if Prologue.null path then "unknown, concrete semantics required" else path
in moduleInclusion (moduleVertex (ModuleInfo path'))
-- | Add vertices to the graph for imported modules.
graphingModuleInfo :: forall term address value effects a
. ( Effects effects
, Member (Modules address) effects
. ( Member (Modules address) effects
, Member (Reader ModuleInfo) effects
, Member (State (Graph ModuleInfo)) effects
, PureEffects effects
)
=> SubtermAlgebra Module term (TermEvaluator term address value effects a)
-> SubtermAlgebra Module term (TermEvaluator term address value effects a)
@ -167,5 +191,6 @@ appendGraph :: (Effectful m, Member (State (Graph v)) effects) => Graph v -> m e
appendGraph = modify' . (<>)
graphing :: (Effectful m, Effects effects) => m (State (Graph Vertex) ': effects) result -> m effects (Graph Vertex, result)
graphing = runState mempty
graphing :: (Effectful m, Effects effects, Functor (m (State (Graph Vertex) : effects)))
=> m (State (Map (Hole context (Located address)) Vertex) ': State (Graph Vertex) ': effects) result -> m effects (Graph Vertex, result)
graphing = runState mempty . fmap snd . runState lowerBound

View File

@ -1,6 +1,8 @@
{-# LANGUAGE GADTs, RankNTypes, TypeFamilies, TypeOperators, UndecidableInstances #-}
module Control.Abstract.Addressable
( Addressable(..)
, Allocatable(..)
, Derefable(..)
) where
import Control.Abstract.Context
@ -11,39 +13,54 @@ import Data.Abstract.Name
import Prologue
-- | Defines allocation and dereferencing of addresses.
class (Ord address, Show address) => Addressable address effects where
class (Ord address, Show address) => Addressable address (effects :: [(* -> *) -> * -> *]) where
-- | The type into which stored values will be written for a given address type.
type family Cell address :: * -> *
class Addressable address effects => Allocatable address effects where
allocCell :: Name -> Evaluator address value effects address
class Addressable address effects => Derefable address effects where
derefCell :: address -> Cell address value -> Evaluator address value effects (Maybe value)
-- | 'Precise' addresses are always allocated a fresh address, and dereference to the 'Latest' value written.
instance Member Fresh effects => Addressable Precise effects where
instance Addressable Precise effects where
type Cell Precise = Latest
instance Member Fresh effects => Allocatable Precise effects where
allocCell _ = Precise <$> fresh
instance Derefable Precise effects where
derefCell _ = pure . getLast . unLatest
-- | 'Monovariant' addresses allocate one address per unique variable name, and dereference once per stored value, nondeterministically.
instance Member NonDet effects => Addressable Monovariant effects where
instance Addressable Monovariant effects where
type Cell Monovariant = All
instance Allocatable Monovariant effects where
allocCell = pure . Monovariant
instance Member NonDet effects => Derefable Monovariant effects where
derefCell _ = traverse (foldMapA pure) . nonEmpty . toList
-- | 'Located' addresses allocate & dereference using the underlying address, contextualizing addresses with the current 'PackageInfo' & 'ModuleInfo'.
instance (Addressable address effects, Member (Reader ModuleInfo) effects, Member (Reader PackageInfo) effects) => Addressable (Located address) effects where
instance Addressable address effects => Addressable (Located address) effects where
type Cell (Located address) = Cell address
allocCell name = relocate (Located <$> allocCell name <*> currentPackage <*> currentModule)
derefCell (Located loc _ _) = relocate . derefCell loc
instance (Allocatable address effects, Member (Reader ModuleInfo) effects, Member (Reader PackageInfo) effects, Member (Reader Span) effects) => Allocatable (Located address) effects where
allocCell name = relocate (Located <$> allocCell name <*> currentPackage <*> currentModule <*> pure name <*> ask)
instance Derefable address effects => Derefable (Located address) effects where
derefCell (Located loc _ _ _ _) = relocate . derefCell loc
instance (Addressable address effects, Ord context, Show context) => Addressable (Hole context address) effects where
type Cell (Hole context address) = Cell address
instance (Allocatable address effects, Ord context, Show context) => Allocatable (Hole context address) effects where
allocCell name = relocate (Total <$> allocCell name)
instance (Derefable address effects, Ord context, Show context) => Derefable (Hole context address) effects where
derefCell (Total loc) = relocate . derefCell loc
derefCell (Partial _) = const (pure Nothing)

View File

@ -4,6 +4,7 @@ module Control.Abstract.Environment
, Exports
, getEnv
, putEnv
, withEnv
, export
, lookupEnv
, bind
@ -20,7 +21,7 @@ module Control.Abstract.Environment
) where
import Control.Abstract.Evaluator
import Data.Abstract.Environment (Environment)
import Data.Abstract.Environment (Bindings, Environment)
import qualified Data.Abstract.Environment as Env
import Data.Abstract.Exports as Exports
import Data.Abstract.Name
@ -34,6 +35,18 @@ getEnv = send GetEnv
putEnv :: Member (Env address) effects => Environment address -> Evaluator address value effects ()
putEnv = send . PutEnv
-- | Replace the environment for a computation
withEnv :: Member (Env address) effects
=> Environment address
-> Evaluator address value effects a
-> Evaluator address value effects a
withEnv env comp = do
oldEnv <- getEnv
putEnv env
value <- comp
putEnv oldEnv
pure value
-- | Add an export to the global export state.
export :: Member (Env address) effects => Name -> Name -> Maybe address -> Evaluator address value effects ()
export name alias addr = send (Export name alias addr)
@ -48,8 +61,8 @@ bind :: Member (Env address) effects => Name -> address -> Evaluator address val
bind name addr = send (Bind name addr)
-- | Bind all of the names from an 'Environment' in the current scope.
bindAll :: Member (Env address) effects => Environment address -> Evaluator address value effects ()
bindAll = foldr ((>>) . uncurry bind) (pure ()) . Env.flatPairs
bindAll :: Member (Env address) effects => Bindings address -> Evaluator address value effects ()
bindAll = foldr ((>>) . uncurry bind) (pure ()) . Env.pairs
-- | Run an action in a new local scope.
locally :: forall address value effects a . Member (Env address) effects => Evaluator address value effects a -> Evaluator address value effects a
@ -70,6 +83,7 @@ data Env address m return where
PutEnv :: Environment address -> Env address m ()
Export :: Name -> Name -> Maybe address -> Env address m ()
instance PureEffect (Env address)
instance Effect (Env address) where
handleState c dist (Request (Lookup name) k) = Request (Lookup name) (dist . (<$ c) . k)
handleState c dist (Request (Bind name addr) k) = Request (Bind name addr) (dist . (<$ c) . k)
@ -79,22 +93,24 @@ instance Effect (Env address) where
handleState c dist (Request (PutEnv e) k) = Request (PutEnv e) (dist . (<$ c) . k)
handleState c dist (Request (Export name alias addr) k) = Request (Export name alias addr) (dist . (<$ c) . k)
-- | Runs a computation in the context of an existing environment.
-- New bindings created in the computation are returned.
runEnv :: Effects effects
=> Environment address
-> Evaluator address value (Env address ': effects) a
-> Evaluator address value effects (Environment address, a)
-> Evaluator address value effects (Bindings address, a)
runEnv initial = fmap (filterEnv . fmap (first Env.head)) . runState lowerBound . runState (Env.push initial) . reinterpret2 handleEnv
where -- TODO: If the set of exports is empty because no exports have been
-- defined, do we export all terms, or no terms? This behavior varies across
-- languages. We need better semantics rather than doing it ad-hoc.
filterEnv (ports, (binds, a))
| Exports.null ports = (Env.newEnv binds, a)
| otherwise = (Env.newEnv (Exports.toBindings ports <> Env.aliasBindings (Exports.aliases ports) binds), a)
| Exports.null ports = (binds, a)
| otherwise = (Exports.toBindings ports <> Env.aliasBindings (Exports.aliases ports) binds, a)
handleEnv :: forall address value effects a . Effects effects => Env address (Eff (Env address ': effects)) a -> Evaluator address value (State (Environment address) ': State (Exports address) ': effects) a
handleEnv = \case
Lookup name -> Env.lookup name <$> get
Bind name addr -> modify (Env.insert name addr)
Lookup name -> Env.lookupEnv' name <$> get
Bind name addr -> modify (Env.insertEnv name addr)
Close names -> Env.intersect names <$> get
Locally action -> do
modify' (Env.push @address)

View File

@ -19,6 +19,8 @@ module Control.Abstract.Heap
-- * Effects
, Allocator(..)
, runAllocator
, Deref(..)
, runDeref
, AddressError(..)
, runAddressError
, runAddressErrorWith
@ -68,7 +70,7 @@ alloc :: Member (Allocator address value) effects => Name -> Evaluator address v
alloc = sendAllocator . Alloc
-- | Dereference the given address in the heap, or fail if the address is uninitialized.
deref :: Member (Allocator address value) effects => address -> Evaluator address value effects value
deref :: Member (Deref address value) effects => address -> Evaluator address value effects value
deref = send . Deref
@ -154,15 +156,16 @@ sendAllocator = send
data Allocator address value (m :: * -> *) return where
Alloc :: Name -> Allocator address value m address
Deref :: address -> Allocator address value m value
Assign :: address -> value -> Allocator address value m ()
GC :: Live address -> Allocator address value m ()
runAllocator :: ( Addressable address effects
, Effects effects
data Deref address value (m :: * -> *) return where
Deref :: address -> Deref address value m value
runAllocator :: ( Allocatable address effects
, Foldable (Cell address)
, Member (Resumable (AddressError address value)) effects
, Member (State (Heap address (Cell address) value)) effects
, PureEffects effects
, Reducer value (Cell address value)
, ValueRoots address value
)
@ -170,16 +173,30 @@ runAllocator :: ( Addressable address effects
-> Evaluator address value effects a
runAllocator = interpret $ \ eff -> case eff of
Alloc name -> allocCell name
Deref addr -> heapLookup addr <$> get >>= maybeM (throwResumable (UnallocatedAddress addr)) >>= derefCell addr >>= maybeM (throwResumable (UninitializedAddress addr))
Assign addr value -> modifyHeap (heapInsert addr value)
GC roots -> modifyHeap (heapRestrict <*> reachable roots)
runDeref :: ( Derefable address effects
, PureEffects effects
, Member (Resumable (AddressError address value)) effects
, Member (State (Heap address (Cell address) value)) effects
)
=> Evaluator address value (Deref address value ': effects) a
-> Evaluator address value effects a
runDeref = interpret $ \ eff -> case eff of
Deref addr -> heapLookup addr <$> get >>= maybeM (throwResumable (UnallocatedAddress addr)) >>= derefCell addr >>= maybeM (throwResumable (UninitializedAddress addr))
instance PureEffect (Allocator address value)
instance Effect (Allocator address value) where
handleState c dist (Request (Alloc name) k) = Request (Alloc name) (dist . (<$ c) . k)
handleState c dist (Request (Deref addr) k) = Request (Deref addr) (dist . (<$ c) . k)
handleState c dist (Request (Assign addr value) k) = Request (Assign addr value) (dist . (<$ c) . k)
handleState c dist (Request (GC roots) k) = Request (GC roots) (dist . (<$ c) . k)
instance PureEffect (Deref address value)
instance Effect (Deref address value) where
handleState c dist (Request (Deref addr) k) = Request (Deref addr) (dist . (<$ c) . k)
data AddressError address value resume where
UnallocatedAddress :: address -> AddressError address value (Cell address value)

View File

@ -1,6 +1,7 @@
{-# LANGUAGE GADTs, LambdaCase, KindSignatures, RankNTypes, ScopedTypeVariables, TypeOperators #-}
module Control.Abstract.Modules
( lookupModule
( ModuleResult
, lookupModule
, resolve
, listModulesInDir
, require
@ -27,8 +28,10 @@ import qualified Data.Set as Set
import Prologue
import System.FilePath.Posix (takeDirectory)
type ModuleResult address = (Bindings address, address)
-- | Retrieve an evaluated module, if any. @Nothing@ means weve never tried to load it, and @Just (env, value)@ indicates the result of a completed load.
lookupModule :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (Maybe (Environment address, address))
lookupModule :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (Maybe (ModuleResult address))
lookupModule = sendModules . Lookup
-- | Resolve a list of module paths to a possible module table entry.
@ -42,22 +45,23 @@ listModulesInDir = sendModules . List
-- | Require/import another module by name and return its environment and value.
--
-- Looks up the module's name in the cache of evaluated modules first, returns if found, otherwise loads/evaluates the module.
require :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (Environment address, address)
require :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (ModuleResult address)
require path = lookupModule path >>= maybeM (load path)
-- | Load another module by name and return its environment and value.
--
-- Always loads/evaluates.
load :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (Environment address, address)
load :: Member (Modules address) effects => ModulePath -> Evaluator address value effects (ModuleResult address)
load path = sendModules (Load path)
data Modules address (m :: * -> *) return where
Load :: ModulePath -> Modules address m (Environment address, address)
Lookup :: ModulePath -> Modules address m (Maybe (Environment address, address))
Load :: ModulePath -> Modules address m (ModuleResult address)
Lookup :: ModulePath -> Modules address m (Maybe (ModuleResult address))
Resolve :: [FilePath] -> Modules address m (Maybe ModulePath)
List :: FilePath -> Modules address m [ModulePath]
instance PureEffect (Modules address)
instance Effect (Modules address) where
handleState c dist (Request (Load path) k) = Request (Load path) (dist . (<$ c) . k)
handleState c dist (Request (Lookup path) k) = Request (Lookup path) (dist . (<$ c) . k)
@ -67,9 +71,9 @@ instance Effect (Modules address) where
sendModules :: Member (Modules address) effects => Modules address (Eff effects) return -> Evaluator address value effects return
sendModules = send
runModules :: ( Effects effects
, Member (Reader (ModuleTable (NonEmpty (Module (Environment address, address))))) effects
runModules :: ( Member (Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))) effects
, Member (Resumable (LoadError address)) effects
, PureEffects effects
)
=> Set ModulePath
-> Evaluator address value (Modules address ': effects) a
@ -80,19 +84,19 @@ runModules paths = interpret $ \case
Resolve names -> pure (find (`Set.member` paths) names)
List dir -> pure (filter ((dir ==) . takeDirectory) (toList paths))
askModuleTable :: Member (Reader (ModuleTable (NonEmpty (Module (Environment address, address))))) effects => Evaluator address value effects (ModuleTable (NonEmpty (Module (Environment address, address))))
askModuleTable :: Member (Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))) effects => Evaluator address value effects (ModuleTable (NonEmpty (Module (ModuleResult address))))
askModuleTable = ask
newtype Merging address = Merging { runMerging :: (Environment address, address) }
newtype Merging address = Merging { runMerging :: ModuleResult address }
instance Semigroup (Merging address) where
Merging (env1, _) <> Merging (env2, addr) = Merging (mergeEnvs env1 env2, addr)
Merging (binds1, _) <> Merging (binds2, addr) = Merging (binds1 <> binds2, addr)
-- | An error thrown when loading a module from the list of provided modules. Indicates we weren't able to find a module with the given name.
data LoadError address resume where
ModuleNotFound :: ModulePath -> LoadError address (Environment address, address)
ModuleNotFound :: ModulePath -> LoadError address (ModuleResult address)
deriving instance Eq (LoadError address resume)
deriving instance Show (LoadError address resume)
@ -101,7 +105,7 @@ instance Show1 (LoadError address) where
instance Eq1 (LoadError address) where
liftEq _ (ModuleNotFound a) (ModuleNotFound b) = a == b
moduleNotFound :: Member (Resumable (LoadError address)) effects => ModulePath -> Evaluator address value effects (Environment address, address)
moduleNotFound :: Member (Resumable (LoadError address)) effects => ModulePath -> Evaluator address value effects (ModuleResult address)
moduleNotFound = throwResumable . ModuleNotFound
runLoadError :: (Effectful (m address value), Effects effects) => m address value (Resumable (LoadError address) ': effects) a -> m address value effects (Either (SomeExc (LoadError address)) a)

View File

@ -57,10 +57,8 @@ defineNamespace :: ( AbstractValue address value effects
-> Evaluator address value effects a
-> Evaluator address value effects ()
defineNamespace name scope = define name $ do
env <- locally $ do
void scope
Env.newEnv . Env.head <$> getEnv
namespace name env
binds <- Env.head <$> locally (scope >> getEnv)
namespace name Nothing binds
lambda :: ( AbstractFunction address value effects
, HasCallStack
@ -77,6 +75,7 @@ lambda body = withCurrentCallStack callStack $ do
builtInPrint :: ( AbstractValue address value effects
, HasCallStack
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member Fresh effects
, Member (Reader ModuleInfo) effects
@ -90,6 +89,7 @@ builtInPrint = lambda (\ v -> variable v >>= deref >>= asString >>= trace . unpa
builtInExport :: ( AbstractValue address value effects
, HasCallStack
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member Fresh effects
, Member (Reader ModuleInfo) effects

View File

@ -140,7 +140,8 @@ class (AbstractFunction address value effects, AbstractIntro value) => AbstractV
--
-- Namespaces model closures with monoidal environments.
namespace :: Name -- ^ The namespace's identifier
-> Environment address -- ^ The environment to mappend
-> Maybe address -- The ancestor of the namespace
-> Bindings address -- ^ The environment to mappend
-> Evaluator address value effects value
-- | Extract the environment from any scoped object (e.g. classes, namespaces, etc).
@ -193,12 +194,11 @@ makeNamespace :: ( AbstractValue address value effects
=> Name
-> address
-> Maybe address
-> Evaluator address value effects ()
-> Evaluator address value effects value
makeNamespace name addr super = do
superEnv <- maybe (pure (Just lowerBound)) scopedEnvironment super
let env' = fromMaybe lowerBound superEnv
namespaceEnv <- newEnv . Env.head <$> getEnv
v <- namespace name (Env.mergeNewer env' namespaceEnv)
makeNamespace name addr super body = do
namespaceBinds <- Env.head <$> locally (body >> getEnv)
v <- namespace name super namespaceBinds
v <$ assign addr v
@ -211,12 +211,13 @@ evaluateInScopedEnv :: ( AbstractValue address value effects
-> Evaluator address value effects a
evaluateInScopedEnv scopedEnvTerm term = do
scopedEnv <- scopedEnvironment scopedEnvTerm
maybe term (\ env -> locally (bindAll env *> term)) scopedEnv
env <- maybeM getEnv scopedEnv
withEnv env term
-- | Evaluates a 'Value' returning the referenced value
value :: ( AbstractValue address value effects
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member (Resumable (EnvironmentError address)) effects
)
@ -226,7 +227,7 @@ value = deref <=< address
-- | Evaluates a 'Subterm' to its rval
subtermValue :: ( AbstractValue address value effects
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member (Resumable (EnvironmentError address)) effects
)

View File

@ -12,6 +12,7 @@ import Data.Abstract.Name
import Data.Abstract.Package (PackageInfo)
import Data.Monoid (Last(..))
import Data.Semigroup.Reducer
import Data.Span
import Data.Set as Set
import Prologue
@ -35,6 +36,8 @@ data Located address = Located
{ address :: address
, addressPackage :: {-# UNPACK #-} !PackageInfo
, addressModule :: !ModuleInfo
, addressName :: Name
, addressSpan :: Span
}
deriving (Eq, Ord, Show)

View File

@ -3,14 +3,15 @@ module Data.Abstract.Environment
, Bindings(..)
, addresses
, aliasBindings
, allNames
, delete
, flatPairs
, head
, insert
, insertEnv
, intersect
, lookup
, mergeEnvs
, mergeNewer
, lookupEnv'
, names
, newEnv
, overwrite
@ -23,16 +24,15 @@ module Data.Abstract.Environment
import Data.Abstract.Live
import Data.Abstract.Name
import Data.Align
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Set as Set
import qualified Data.Map as Map
import Prelude hiding (head, lookup)
import Prologue
-- $setup
-- >>> import Data.Abstract.Address
-- >>> let bright = push (insert (name "foo") (Precise 0) lowerBound)
-- >>> let shadowed = insert (name "foo") (Precise 1) bright
-- >>> let bright = push (insertEnv (name "foo") (Precise 0) lowerBound)
-- >>> let shadowed = insertEnv (name "foo") (Precise 1) bright
-- | A map of names to values. Represents a single scope level of an environment chain.
newtype Bindings address = Bindings { unBindings :: Map.Map Name address }
@ -54,10 +54,6 @@ instance Lower (Bindings address) where
newtype Environment address = Environment { unEnvironment :: NonEmpty (Bindings address) }
deriving (Eq, Ord)
mergeEnvs :: Environment address -> Environment address -> Environment address
mergeEnvs (Environment (a :| as)) (Environment (b :| bs)) =
Environment ((<>) a b :| alignWith (mergeThese (<>)) as bs)
-- | Make and enter a new empty scope in the given environment.
push :: Environment address -> Environment address
push (Environment (a :| as)) = Environment (mempty :| a : as)
@ -71,16 +67,6 @@ pop (Environment (_ :| a : as)) = Environment (a :| as)
head :: Environment address -> Bindings address
head (Environment (a :| _)) = a
-- | Take the union of two environments. When duplicate keys are found in the
-- name to address map, the second definition wins.
mergeNewer :: Environment address -> Environment address -> Environment address
mergeNewer (Environment a) (Environment b) =
Environment (NonEmpty.fromList . reverse . fmap Bindings $ alignWith (mergeThese combine) (reverse as) (reverse bs))
where
combine = Map.unionWith (flip const)
as = unBindings <$> toList a
bs = unBindings <$> toList b
-- | Extract an association list of bindings from a 'Bindings'.
--
-- >>> pairs (head shadowed)
@ -97,16 +83,24 @@ flatPairs = (>>= pairs) . toList . unEnvironment
newEnv :: Bindings address -> Environment address
newEnv = Environment . pure
-- | Lookup a 'Name' in the bindings.
lookup :: Name -> Bindings address -> Maybe address
lookup name = Map.lookup name . unBindings
-- | Lookup a 'Name' in the environment.
--
-- >>> lookup (name "foo") shadowed
-- >>> lookupEnv' (name "foo") shadowed
-- Just (Precise 1)
lookup :: Name -> Environment address -> Maybe address
lookup name = foldMapA (Map.lookup name) . fmap unBindings . unEnvironment
lookupEnv' :: Name -> Environment address -> Maybe address
lookupEnv' name = foldMapA (lookup name) . unEnvironment
-- | Insert a 'Name' in the environment.
insert :: Name -> address -> Environment address -> Environment address
insert name addr (Environment (Bindings a :| as)) = Environment (Bindings (Map.insert name addr a) :| as)
-- | Insert a 'Name' in the bindings
insert :: Name -> address -> Bindings address -> Bindings address
insert name addr = Bindings . Map.insert name addr . unBindings
-- | Insert a 'Name' in the environment
insertEnv :: Name -> address -> Environment address -> Environment address
insertEnv name addr (Environment (Bindings a :| as)) = Environment (Bindings (Map.insert name addr a) :| as)
-- | Remove a 'Name' from the environment.
--
@ -122,11 +116,24 @@ trim (Environment (a :| as)) = Environment (a :| filtered)
intersect :: Foldable t => t Name -> Environment address -> Environment address
intersect names env = newEnv (unpairs (mapMaybe lookupName (toList names)))
where
lookupName name = (,) name <$> lookup name env
lookupName name = (,) name <$> lookupEnv' name env
-- | Get all bound 'Name's in a binding.
names :: Bindings address -> [Name]
names = fmap fst . pairs
-- | Order preserving deduplication in O(n log n) time
dedup :: Ord a => [a] -> [a]
dedup = go Set.empty
where
go _ [] = []
go seen (x:xs)
| Set.member x seen = go seen xs
| otherwise = x : go (Set.insert x seen) xs
-- | Get all bound 'Name's in an environment.
names :: Environment address -> [Name]
names = fmap fst . flatPairs
allNames :: Environment address -> [Name]
allNames = dedup . fmap fst . flatPairs
aliasBindings :: [(Name, Name)] -> Bindings address -> Bindings address
aliasBindings pairs binds = unpairs $ mapMaybe lookupAndAlias pairs
@ -137,7 +144,7 @@ aliasBindings pairs binds = unpairs $ mapMaybe lookupAndAlias pairs
overwrite :: [(Name, Name)] -> Environment address -> Environment address
overwrite pairs env = newEnv . unpairs $ mapMaybe lookupAndAlias pairs
where
lookupAndAlias (oldName, newName) = (,) newName <$> lookup oldName env
lookupAndAlias (oldName, newName) = (,) newName <$> lookupEnv' oldName env
-- | Retrieve the 'Live' set of addresses to which the given free variable names are bound.
--

View File

@ -49,6 +49,7 @@ class (Show1 constr, Foldable constr) => Evaluatable constr where
, Declarations term
, FreeVariables term
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member (Exc (LoopControl address)) effects
, Member (Exc (Return address)) effects
@ -71,7 +72,8 @@ class (Show1 constr, Foldable constr) => Evaluatable constr where
evaluate :: ( AbstractValue address value inner
, Addressable address (Reader ModuleInfo ': effects)
, Allocatable address (Reader ModuleInfo ': effects)
, Derefable address (Allocator address value ': Reader ModuleInfo ': effects)
, Declarations term
, Effects effects
, Evaluatable (Base term)
@ -81,7 +83,7 @@ evaluate :: ( AbstractValue address value inner
, HasPrelude lang
, Member Fresh effects
, Member (Modules address) effects
, Member (Reader (ModuleTable (NonEmpty (Module (Environment address, address))))) effects
, Member (Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))) effects
, Member (Reader PackageInfo) effects
, Member (Reader Span) effects
, Member (Resumable (AddressError address value)) effects
@ -94,21 +96,21 @@ evaluate :: ( AbstractValue address value inner
, Recursive term
, Reducer value (Cell address value)
, ValueRoots address value
, inner ~ (Exc (LoopControl address) ': Exc (Return address) ': Env address ': Allocator address value ': Reader ModuleInfo ': effects)
, inner ~ (Exc (LoopControl address) ': Exc (Return address) ': Env address ': Deref address value ': Allocator address value ': Reader ModuleInfo ': effects)
)
=> proxy lang
-> (SubtermAlgebra Module term (TermEvaluator term address value inner address) -> SubtermAlgebra Module term (TermEvaluator term address value inner address))
-> (SubtermAlgebra (Base term) term (TermEvaluator term address value inner (ValueRef address)) -> SubtermAlgebra (Base term) term (TermEvaluator term address value inner (ValueRef address)))
-> [Module term]
-> TermEvaluator term address value effects (ModuleTable (NonEmpty (Module (Environment address, address))))
-> TermEvaluator term address value effects (ModuleTable (NonEmpty (Module (ModuleResult address))))
evaluate lang analyzeModule analyzeTerm modules = do
(preludeEnv, _) <- TermEvaluator . runInModule lowerBound moduleInfoFromCallStack $ do
(preludeBinds, _) <- TermEvaluator . runInModule lowerBound moduleInfoFromCallStack $ do
definePrelude lang
box unit
foldr (run preludeEnv) ask modules
where run preludeEnv m rest = do
foldr (run preludeBinds) ask modules
where run preludeBinds m rest = do
evaluated <- coerce
(runInModule preludeEnv (moduleInfo m))
(runInModule preludeBinds (moduleInfo m))
(analyzeModule (subtermRef . moduleBody)
(evalModuleBody <$> m))
-- FIXME: this should be some sort of Monoidal insert à la the Heap to accommodate multiple Go files being part of the same module.
@ -118,10 +120,11 @@ evaluate lang analyzeModule analyzeTerm modules = do
result <- foldSubterms (analyzeTerm (TermEvaluator . eval . fmap (second runTermEvaluator))) term >>= TermEvaluator . address
result <$ TermEvaluator (postlude lang))
runInModule preludeEnv info
runInModule preludeBinds info
= runReader info
. runAllocator
. runEnv preludeEnv
. runDeref
. runEnv (newEnv preludeBinds)
. runReturn
. runLoopControl
@ -136,6 +139,7 @@ class HasPrelude (language :: Language) where
definePrelude :: ( AbstractValue address value effects
, HasCallStack
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member Fresh effects
, Member (Reader ModuleInfo) effects
@ -179,6 +183,7 @@ class HasPostlude (language :: Language) where
postlude :: ( AbstractValue address value effects
, HasCallStack
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member Fresh effects
, Member (Reader ModuleInfo) effects

View File

@ -28,17 +28,18 @@ instance AbstractIntro Abstract where
null = Abstract
instance ( Member (Allocator address Abstract) effects
, Member (Deref address Abstract) effects
, Member (Env address) effects
, Member (Exc (Return address)) effects
, Member Fresh effects
)
=> AbstractFunction address Abstract effects where
closure names _ body = do
env <- foldr (\ name rest -> do
binds <- foldr (\ name rest -> do
addr <- alloc name
assign addr Abstract
Env.insert name addr <$> rest) (pure lowerBound) names
addr <- locally (bindAll env *> catchReturn body)
addr <- locally (bindAll binds *> catchReturn body)
deref addr
call Abstract params = do
@ -46,6 +47,7 @@ instance ( Member (Allocator address Abstract) effects
box Abstract
instance ( Member (Allocator address Abstract) effects
, Member (Deref address Abstract) effects
, Member (Env address) effects
, Member (Exc (Return address)) effects
, Member NonDet effects
@ -57,7 +59,7 @@ instance ( Member (Allocator address Abstract) effects
tuple _ = pure Abstract
klass _ _ _ = pure Abstract
namespace _ _ = pure Abstract
namespace _ _ _ = pure Abstract
scopedEnvironment _ = pure lowerBound

View File

@ -3,6 +3,7 @@ module Data.Abstract.Value.Concrete
( Value (..)
, ValueError (..)
, ClosureBody (..)
, materializeEnvironment
, runValueError
, runValueErrorWith
, throwValueError
@ -32,7 +33,7 @@ data Value address body
| Tuple [address]
| Array [address]
| Class Name [address] (Bindings address)
| Namespace Name (Environment address)
| Namespace Name (Maybe address) (Bindings address)
| KVPair (Value address body) (Value address body)
| Hash [Value address body]
| Null
@ -85,8 +86,9 @@ instance ( Coercible body (Eff effects)
withCurrentPackage packageInfo . withCurrentModule moduleInfo $ do
bindings <- foldr (\ (name, param) rest -> do
addr <- param
Env.insert name addr <$> rest) (pure env) (zip names params)
locally (catchReturn (bindAll bindings *> raiseEff (coerce body)))
Env.insert name addr <$> rest) (pure lowerBound) (zip names params)
let fnEnv = Env.push env
withEnv fnEnv (catchReturn (bindAll bindings *> raiseEff (coerce body)))
_ -> box =<< throwValueError (CallError op)
@ -104,10 +106,32 @@ instance Show address => AbstractIntro (Value address body) where
null = Null
materializeEnvironment :: ( Member (Deref address (Value address body)) effects
)
=> Value address body
-> Evaluator address (Value address body) effects (Maybe (Environment address))
materializeEnvironment val = do
ancestors <- rec val
pure (Env.Environment <$> nonEmpty ancestors)
where
rec val = do
supers <- concat <$> traverse (deref >=> rec) (parents val)
pure . maybe [] (: supers) $ bindsFrom val
bindsFrom = \case
Class _ _ binds -> Just binds
Namespace _ _ binds -> Just binds
_ -> Nothing
parents = \case
Class _ supers _ -> supers
Namespace _ supers _ -> toList supers
_ -> []
-- | Construct a 'Value' wrapping the value arguments (if any).
instance ( Coercible body (Eff effects)
, Member (Allocator address (Value address body)) effects
, Member (Deref address (Value address body)) effects
, Member (Env address) effects
, Member (Exc (LoopControl address)) effects
, Member (Exc (Return address)) effects
@ -128,21 +152,20 @@ instance ( Coercible body (Eff effects)
klass n supers binds = do
pure $ Class n supers binds
namespace name env = do
maybeAddr <- lookupEnv name
env' <- maybe (pure lowerBound) (asNamespaceEnv <=< deref) maybeAddr
pure (Namespace name (Env.mergeNewer env' env))
where asNamespaceEnv v
| Namespace _ env' <- v = pure env'
| otherwise = throwValueError $ NamespaceError ("expected " <> show v <> " to be a namespace")
namespace name super binds = do
maybeNs <- lookupEnv name >>= traverse deref
binds' <- maybe (pure lowerBound) asNamespaceBinds maybeNs
let super' = (maybeNs >>= asNamespaceSuper) <|> super
pure (Namespace name super' (binds <> binds'))
where
asNamespaceSuper = \case
Namespace _ super _ -> super
_ -> Nothing
asNamespaceBinds v
| Namespace _ _ binds' <- v = pure binds'
| otherwise = throwValueError $ NamespaceError ("expected " <> show v <> " to be a namespace")
scopedEnvironment ptr = do
ancestors <- ancestorBinds [ptr]
pure (Env.Environment <$> nonEmpty ancestors)
where ancestorBinds = (pure . concat) <=< traverse (deref >=> \case
Class _ supers binds -> (binds :) <$> ancestorBinds (reverse supers)
Namespace _ env -> pure . toList . Env.unEnvironment $ env
_ -> pure [])
scopedEnvironment = deref >=> materializeEnvironment
asString v
| String n <- v = pure n
@ -238,7 +261,7 @@ data ValueError address body resume where
StringError :: Value address body -> ValueError address body Text
BoolError :: Value address body -> ValueError address body Bool
IndexError :: Value address body -> Value address body -> ValueError address body (Value address body)
NamespaceError :: Prelude.String -> ValueError address body (Environment address)
NamespaceError :: Prelude.String -> ValueError address body (Bindings address)
CallError :: Value address body -> ValueError address body (Value address body)
NumericError :: Value address body -> ValueError address body (Value address body)
Numeric2Error :: Value address body -> Value address body -> ValueError address body (Value address body)

View File

@ -233,6 +233,7 @@ instance AbstractIntro Type where
instance ( Member (Allocator address Type) effects
, Member (Deref address Type) effects
, Member (Env address) effects
, Member (Exc (Return address)) effects
, Member Fresh effects
@ -241,12 +242,12 @@ instance ( Member (Allocator address Type) effects
)
=> AbstractFunction address Type effects where
closure names _ body = do
(env, tvars) <- foldr (\ name rest -> do
(binds, tvars) <- foldr (\ name rest -> do
addr <- alloc name
tvar <- Var <$> fresh
assign addr tvar
bimap (Env.insert name addr) (tvar :) <$> rest) (pure (lowerBound, [])) names
(zeroOrMoreProduct tvars :->) <$> (deref =<< locally (catchReturn (bindAll env *> body)))
(zeroOrMoreProduct tvars :->) <$> (deref =<< locally (catchReturn (bindAll binds *> body)))
call op params = do
tvar <- fresh
@ -260,6 +261,7 @@ instance ( Member (Allocator address Type) effects
-- | Discard the value arguments (if any), constructing a 'Type' instead.
instance ( Member (Allocator address Type) effects
, Member (Deref address Type) effects
, Member (Env address) effects
, Member (Exc (Return address)) effects
, Member Fresh effects
@ -275,8 +277,8 @@ instance ( Member (Allocator address Type) effects
tuple fields = zeroOrMoreProduct <$> traverse deref fields
klass _ _ _ = pure Object
namespace _ _ = pure Unit
klass _ _ _ = pure Object
namespace _ _ _ = pure Unit
scopedEnvironment _ = pure (Just lowerBound)

View File

@ -42,6 +42,7 @@ import qualified Data.Graph.Vertex as V
data VertexType
= PACKAGE
| MODULE
| UNKNOWN_MODULE
| VARIABLE
| METHOD
| FUNCTION
@ -115,10 +116,11 @@ taggedGraphToAdjacencyList = accumToAdj . adjMapToAccum . adjacencyMap . toGraph
accumToAdj (Acc vs es) = AdjacencyList (fromList vs) (fromList (toList es))
vertexToPB :: V.Vertex -> Tag -> Vertex
vertexToPB s = Vertex t (V.vertexName s) where
vertexToPB s = Vertex t (V.vertexIdentifier s) where
t = case s of
V.Package{} -> PACKAGE
V.Module{} -> MODULE
V.UnknownModule{} -> UNKNOWN_MODULE
V.Variable{} -> VARIABLE
V.Method{} -> METHOD
V.Function{} -> FUNCTION
@ -161,8 +163,9 @@ importGraphToGraph (AdjacencyList vs es) = simplify built
pbToVertex :: Vertex -> V.Vertex
pbToVertex (Vertex t c _) = case t of
MODULE -> V.Module c
PACKAGE -> V.Package c
MODULE -> V.Module c
UNKNOWN_MODULE -> V.UnknownModule c
VARIABLE -> V.Variable c "unknown" emptySpan
METHOD -> V.Method c "unknown" emptySpan
FUNCTION -> V.Function c "unknown" emptySpan

View File

@ -3,10 +3,11 @@ module Data.Graph.Vertex
( Vertex (..)
, packageVertex
, moduleVertex
, unknownModuleVertex
, variableVertex
, methodVertex
, functionVertex
, vertexName
, vertexIdentifier
, showSpan
, VertexDeclaration (..)
, VertexDeclaration' (..)
@ -30,11 +31,12 @@ import Prologue hiding (packageName)
-- | A vertex of some specific type.
data Vertex
= Package { packageName :: Text }
| Module { moduleName :: Text }
| Variable { variableName :: Text, variableModuleName :: Text, variableSpan :: Span }
| Method { methodName :: Text, methodModuleName :: Text, methodSpan :: Span }
| Function { functionName :: Text, functionModuleName :: Text, functionSpan :: Span }
= Package { vertexName :: Text }
| Module { vertexName :: Text }
| UnknownModule { vertexName :: Text }
| Variable { vertexName :: Text, vertexModuleName :: Text, vertexSpan :: Span }
| Method { vertexName :: Text, vertexModuleName :: Text, vertexSpan :: Span }
| Function { vertexName :: Text, vertexModuleName :: Text, vertexSpan :: Span }
deriving (Eq, Ord, Show, Generic, Hashable)
packageVertex :: PackageInfo -> Vertex
@ -43,6 +45,9 @@ packageVertex (PackageInfo name _) = Package (formatName name)
moduleVertex :: ModuleInfo -> Vertex
moduleVertex = Module . T.pack . modulePath
unknownModuleVertex :: ModuleInfo -> Vertex
unknownModuleVertex = UnknownModule . T.pack . modulePath
variableVertex :: Text -> ModuleInfo -> Span -> Vertex
variableVertex name ModuleInfo{..} = Variable name (T.pack modulePath)
@ -53,14 +58,13 @@ functionVertex :: Text -> ModuleInfo -> Span -> Vertex
functionVertex name ModuleInfo{..} = Function name (T.pack modulePath)
instance ToJSON Vertex where
toJSON v = object [ "name" .= vertexName v, "type" .= vertexToType v ]
toJSON v = object [ "name" .= vertexIdentifier v, "type" .= vertexToType v ]
vertexName :: Vertex -> Text
vertexName Package{..} = packageName <> " (Package)"
vertexName Module{..} = moduleName <> " (Module)"
vertexName Variable{..} = variableModuleName <> "::" <> variableName <> " (Variable)"
vertexName Method{..} = methodModuleName <> "::" <> methodName <> " (Method)"
vertexName Function{..} = functionModuleName <> "::" <> functionName <> " (Function)"
vertexIdentifier :: Vertex -> Text
vertexIdentifier v@Package{..} = vertexName <> " (" <> vertexToType v <> ")"
vertexIdentifier v@Module{..} = vertexName <> " (" <> vertexToType v <> ")"
vertexIdentifier v@UnknownModule{..} = vertexName <> " (" <> vertexToType v <> ")"
vertexIdentifier v = vertexModuleName v <> "::" <> vertexName v <> " (" <> vertexToType v <> " " <> showSpan (vertexSpan v) <> ")"
showSpan :: Span -> Text
showSpan (Span (Pos a b) (Pos c d)) = T.pack $
@ -69,11 +73,12 @@ showSpan (Span (Pos a b) (Pos c d)) = T.pack $
<> "[" <> show c <> ", " <> show d <> "]"
vertexToType :: Vertex -> Text
vertexToType Package{} = "package"
vertexToType Module{} = "module"
vertexToType Variable{} = "variable"
vertexToType Method{} = "method"
vertexToType Function{} = "function"
vertexToType Package{} = "Package"
vertexToType Module{} = "Module"
vertexToType UnknownModule{} = "Unknown Module"
vertexToType Variable{} = "Variable"
vertexToType Method{} = "Method"
vertexToType Function{} = "Function"
instance Lower Vertex where
lowerBound = Package ""

View File

@ -139,15 +139,25 @@ instance Show1 Null where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Null where eval _ = rvalBox null
newtype Symbol a = Symbol { symbolContent :: Text }
newtype Symbol a = Symbol { symbolElements :: [a] }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
instance Eq1 Symbol where liftEq = genericLiftEq
instance Ord1 Symbol where liftCompare = genericLiftCompare
instance Show1 Symbol where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Symbol where
eval (Symbol s) = rvalBox (symbol s)
-- TODO: Implement Eval instance for Symbol
instance Evaluatable Symbol
newtype SymbolElement a = SymbolElement { symbolContent :: Text }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
instance Eq1 SymbolElement where liftEq = genericLiftEq
instance Ord1 SymbolElement where liftCompare = genericLiftCompare
instance Show1 SymbolElement where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable SymbolElement where
eval (SymbolElement s) = rvalBox (symbol s)
newtype Regex a = Regex { regexContent :: Text }
deriving (Diffable, Eq, Foldable, Functor, Generic1, Hashable1, Ord, Show, Traversable, FreeVariables1, Declarations1, ToJSONFields1, Named1, Message1)

View File

@ -235,7 +235,7 @@ instance Show1 Retry where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Retry
newtype NoOp a = NoOp a
newtype NoOp a = NoOp { value :: a }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
instance Eq1 NoOp where liftEq = genericLiftEq

View File

@ -87,11 +87,10 @@ instance Evaluatable QualifiedImport where
paths <- resolveGoImport importPath
alias <- maybeM (throwEvalError NoNameError) (declaredName (subterm aliasTerm))
void . letrec' alias $ \addr -> do
for_ paths $ \p -> do
makeNamespace alias addr Nothing . for_ paths $ \p -> do
traceResolve (unPath importPath) p
importedEnv <- fst <$> require p
bindAll importedEnv
makeNamespace alias addr Nothing
rvalBox unit
-- | Side effect only imports (no symbols made available to the calling environment).

View File

@ -2,6 +2,7 @@
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
module Language.PHP.Syntax where
import Control.Abstract.Modules
import Data.Abstract.Evaluatable
import Data.Abstract.Module
import Data.Abstract.Path
@ -48,7 +49,7 @@ resolvePHPName n = do
toName = T.unpack . dropRelativePrefix . stripQuotes
include :: ( AbstractValue address value effects
, Member (Allocator address value) effects
, Member (Deref address value) effects
, Member (Env address) effects
, Member (Modules address) effects
, Member (Resumable ResolutionError) effects
@ -56,7 +57,7 @@ include :: ( AbstractValue address value effects
, Member Trace effects
)
=> Subterm term (Evaluator address value effects (ValueRef address))
-> (ModulePath -> Evaluator address value effects (Environment address, address))
-> (ModulePath -> Evaluator address value effects (ModuleResult address))
-> Evaluator address value effects (ValueRef address)
include pathTerm f = do
name <- subtermValue pathTerm >>= asString
@ -370,20 +371,20 @@ instance Ord1 Namespace where liftCompare = genericLiftCompare
instance Show1 Namespace where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Namespace where
eval Namespace{..} = rvalBox =<< go (declaredName . subterm <$> namespaceName)
eval Namespace{..} = Rval <$> go (declaredName . subterm <$> namespaceName)
where
-- Each namespace name creates a closure over the subsequent namespace closures
go (n:x:xs) = do
name <- maybeM (throwResumable NoNameError) n
letrec' name $ \addr ->
go (x:xs) <* makeNamespace name addr Nothing
box =<< makeNamespace name addr Nothing (void $ go (x:xs))
-- The last name creates a closure over the namespace body.
go [n] = do
name <- maybeM (throwResumable NoNameError) n
letrec' name $ \addr ->
subtermValue namespaceBody *> makeNamespace name addr Nothing
box =<< makeNamespace name addr Nothing (void $ subtermAddress namespaceBody)
-- The absence of names implies global scope, cf http://php.net/manual/en/language.namespaces.definitionmultiple.php
go [] = subtermValue namespaceBody
go [] = subtermAddress namespaceBody
data TraitDeclaration a = TraitDeclaration { traitName :: a, traitStatements :: [a] }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable)

View File

@ -1,4 +1,5 @@
{-# LANGUAGE DataKinds, RankNTypes, TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} -- FIXME
module Language.Python.Assignment
( assignment
, Syntax
@ -6,10 +7,14 @@ module Language.Python.Assignment
, Term
) where
import Assigning.Assignment hiding (Assignment, Error)
import Data.Abstract.Name (Name, name)
import Data.Record
import Data.Syntax
import Assigning.Assignment hiding (Assignment, Error)
import qualified Assigning.Assignment as Assignment
import Data.Abstract.Name (Name, name)
import qualified Data.Diff as Diff
import qualified Data.List.NonEmpty as NonEmpty
import Data.Record
import Data.Sum
import Data.Syntax
( contextualize
, emptyTerm
, handleError
@ -21,11 +26,6 @@ import Data.Syntax
, parseError
, postContextualize
)
import Language.Python.Grammar as Grammar
import Language.Python.Syntax as Python.Syntax
import qualified Assigning.Assignment as Assignment
import qualified Data.List.NonEmpty as NonEmpty
import Data.Sum
import qualified Data.Syntax as Syntax
import qualified Data.Syntax.Comment as Comment
import qualified Data.Syntax.Declaration as Declaration
@ -35,7 +35,10 @@ import qualified Data.Syntax.Statement as Statement
import qualified Data.Syntax.Type as Type
import qualified Data.Term as Term
import qualified Data.Text as T
import Prologue
import Language.Python.Grammar as Grammar
import Language.Python.Syntax as Python.Syntax
import Prologue
import Proto3.Suite (Named (..), Named1 (..))
-- | The type of Python syntax.
@ -120,6 +123,15 @@ type Syntax =
type Term = Term.Term (Sum Syntax) (Record Location)
type Assignment = Assignment.Assignment [] Grammar
instance Named1 (Sum Syntax) where
nameOf1 _ = "PythonSyntax"
instance Named (Term.Term (Sum Syntax) ()) where
nameOf _ = "PythonTerm"
instance Named (Diff.Diff (Sum Syntax) () ()) where
nameOf _ = "PythonDiff"
-- | Assignment from AST in Python's grammar onto a program in Python's syntax.
assignment :: Assignment Term
assignment = handleError $ makeTerm <$> symbol Module <*> children (Statement.Statements <$> manyTerm expression) <|> parseError
@ -415,8 +427,8 @@ import' = makeTerm'' <$> symbol ImportStatement <*> children (manyTerm (aliase
identifierSource = (symbol Identifier <|> symbol Identifier') *> source
aliasIdentifier = (symbol Identifier <|> symbol Identifier') *> (name <$> source) <|> symbol DottedName *> (name <$> source)
makeNameAliasPair from (Just alias) = (from, alias)
makeNameAliasPair from Nothing = (from, from)
makeNameAliasPair from (Just alias) = Python.Syntax.Alias from alias
makeNameAliasPair from Nothing = Python.Syntax.Alias from from
assertStatement :: Assignment Term
assertStatement = makeTerm <$> symbol AssertStatement <*> children (Expression.Call [] <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier . name <$> source)) <*> manyTerm expression <*> emptyTerm)

View File

@ -1,5 +1,6 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} -- FIXME
module Language.Python.Syntax where
import Data.Abstract.Environment as Env
@ -15,11 +16,24 @@ import Diffing.Algorithm
import GHC.Generics
import Prologue
import System.FilePath.Posix
import Proto3.Suite (Primitive(..), Message(..), Message1(..), Named1(..), Named(..), MessageField(..), DotProtoIdentifier(..), DotProtoPrimType(..), DotProtoType(..), messageField)
import qualified Proto3.Suite as Proto
import qualified Proto3.Wire.Encode as Encode
import qualified Proto3.Wire.Decode as Decode
data QualifiedName
= QualifiedName (NonEmpty FilePath)
| RelativeQualifiedName FilePath (Maybe QualifiedName)
deriving (Eq, Generic, Hashable, Ord, Show, ToJSON)
= QualifiedName { paths :: NonEmpty FilePath }
| RelativeQualifiedName { path :: FilePath, maybeQualifiedName :: Maybe QualifiedName }
deriving (Eq, Generic, Hashable, Ord, Show, ToJSON, Named, Message)
instance MessageField QualifiedName where
encodeMessageField num QualifiedName{..} = Encode.embedded num (encodeMessageField 1 paths)
encodeMessageField num RelativeQualifiedName{..} = Encode.embedded num (encodeMessageField 1 path <> encodeMessageField 2 maybeQualifiedName)
decodeMessageField = Decode.embedded'' (qualifiedName <|> relativeQualifiedName)
where
qualifiedName = QualifiedName <$> Decode.at decodeMessageField 1
relativeQualifiedName = RelativeQualifiedName <$> Decode.at decodeMessageField 1 <*> Decode.at decodeMessageField 2
protoType _ = messageField (Prim $ Named (Single (nameOf (Proxy @QualifiedName)))) Nothing
qualifiedName :: NonEmpty Text -> QualifiedName
qualifiedName xs = QualifiedName (T.unpack <$> xs)
@ -86,20 +100,27 @@ resolvePythonModules q = do
-- | Import declarations (symbols are added directly to the calling environment).
--
-- If the list of symbols is empty copy everything to the calling environment.
data Import a = Import { importFrom :: QualifiedName, importSymbols :: ![(Name, Name)] }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable)
data Import a = Import { importFrom :: QualifiedName, importSymbols :: ![Alias] }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
instance Eq1 Import where liftEq = genericLiftEq
instance Ord1 Import where liftCompare = genericLiftCompare
instance Show1 Import where liftShowsPrec = genericLiftShowsPrec
data Alias = Alias { aliasValue :: Name, aliasName :: Name }
deriving (Eq, Generic, Hashable, Ord, Show, Message, Named, ToJSON)
toTuple :: Alias -> (Name, Name)
toTuple Alias{..} = (aliasValue, aliasName)
-- from a import b
instance Evaluatable Import where
-- from . import moduleY
-- This is a bit of a special case in the syntax as this actually behaves like a qualified relative import.
eval (Import (RelativeQualifiedName n Nothing) [(name, _)]) = do
path <- NonEmpty.last <$> resolvePythonModules (RelativeQualifiedName n (Just (qualifiedName (formatName name :| []))))
rvalBox =<< evalQualifiedImport name path
eval (Import (RelativeQualifiedName n Nothing) [Alias{..}]) = do
path <- NonEmpty.last <$> resolvePythonModules (RelativeQualifiedName n (Just (qualifiedName (formatName aliasValue :| []))))
rvalBox =<< evalQualifiedImport aliasValue path
-- from a import b
-- from a import b as c
@ -113,13 +134,13 @@ instance Evaluatable Import where
-- Last module path is the one we want to import
let path = NonEmpty.last modulePaths
importedEnv <- fst <$> require path
bindAll (select importedEnv)
importedBinds <- fst <$> require path
bindAll (select importedBinds)
rvalBox unit
where
select importedEnv
| Prologue.null xs = importedEnv
| otherwise = Env.overwrite xs importedEnv
select importedBinds
| Prologue.null xs = importedBinds
| otherwise = Env.aliasBindings (toTuple <$> xs) importedBinds
-- Evaluate a qualified import
@ -130,12 +151,22 @@ evalQualifiedImport :: ( AbstractValue address value effects
)
=> Name -> ModulePath -> Evaluator address value effects value
evalQualifiedImport name path = letrec' name $ \addr -> do
importedEnv <- fst <$> require path
bindAll importedEnv
unit <$ makeNamespace name addr Nothing
unit <$ makeNamespace name addr Nothing (bindAll . fst =<< require path)
newtype QualifiedImport a = QualifiedImport { qualifiedImportFrom :: NonEmpty FilePath }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable)
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Named1, Ord, Show, ToJSONFields1, Traversable)
instance Message1 QualifiedImport where
liftEncodeMessage _ _ QualifiedImport{..} = encodeMessageField 1 qualifiedImportFrom
liftDecodeMessage _ _ = QualifiedImport <$> Decode.at decodeMessageField 1
liftDotProto _ = [ Proto.DotProtoMessageField $ Proto.DotProtoField 1 (Repeated Proto.String) (Single "qualifiedImportFrom") [] Nothing ]
instance Named Prelude.String where nameOf _ = "string"
instance Message Prelude.String where
encodeMessage _ = encodePrimitive 1
decodeMessage _ = Decode.at (Decode.one decodePrimitive mempty) 1
dotProto = undefined
instance Eq1 QualifiedImport where liftEq = genericLiftEq
instance Ord1 QualifiedImport where liftCompare = genericLiftCompare
@ -152,11 +183,10 @@ instance Evaluatable QualifiedImport where
-- Evaluate each parent module, just creating a namespace
go ((name, path) :| xs) = letrec' name $ \addr -> do
void $ require path
void $ go (NonEmpty.fromList xs)
makeNamespace name addr Nothing
makeNamespace name addr Nothing (void (require path >> go (NonEmpty.fromList xs)))
data QualifiedAliasedImport a = QualifiedAliasedImport { qualifiedAliasedImportFrom :: QualifiedName, qualifiedAliasedImportAlias :: !a }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable)
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
instance Eq1 QualifiedAliasedImport where liftEq = genericLiftEq
instance Ord1 QualifiedAliasedImport where liftCompare = genericLiftCompare
@ -174,13 +204,11 @@ instance Evaluatable QualifiedAliasedImport where
alias <- maybeM (throwEvalError NoNameError) (declaredName (subterm aliasTerm))
rvalBox =<< letrec' alias (\addr -> do
let path = NonEmpty.last modulePaths
importedEnv <- fst <$> require path
bindAll importedEnv
unit <$ makeNamespace alias addr Nothing)
unit <$ makeNamespace alias addr Nothing (void (bindAll . fst =<< require path)))
-- | Ellipsis (used in splice expressions and alternatively can be used as a fill in expression, like `undefined` in Haskell)
data Ellipsis a = Ellipsis
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable)
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
instance Eq1 Ellipsis where liftEq = genericLiftEq
instance Ord1 Ellipsis where liftCompare = genericLiftCompare
@ -190,8 +218,8 @@ instance Show1 Ellipsis where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Ellipsis
data Redirect a = Redirect !a !a
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable)
data Redirect a = Redirect { lhs :: a, rhs :: a }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
instance Eq1 Redirect where liftEq = genericLiftEq
instance Ord1 Redirect where liftCompare = genericLiftCompare

View File

@ -82,16 +82,19 @@ type Syntax = '[
, Expression.Subscript
, Expression.Member
, Literal.Array
, Literal.Character
, Literal.Complex
, Literal.Float
, Literal.Hash
, Literal.Integer
, Literal.InterpolationElement
, Literal.KeyValue
, Literal.Null
, Literal.Rational
, Literal.Regex
, Literal.String
, Literal.Symbol
, Literal.SymbolElement
, Literal.TextElement
, Statement.Assignment
, Statement.Break
@ -250,16 +253,32 @@ literal =
-- TODO: Do we want to represent the difference between .. and ...
<|> makeTerm <$> symbol Range <*> children (Expression.Enumeration <$> expression <*> expression <*> emptyTerm)
<|> makeTerm <$> symbol Array <*> children (Literal.Array <$> many expression)
<|> makeTerm <$> symbol StringArray <*> children (Literal.Array <$> many expression)
<|> makeTerm <$> symbol SymbolArray <*> children (Literal.Array <$> many expression)
<|> makeTerm <$> symbol Hash <*> children (Literal.Hash <$> many expression)
<|> makeTerm <$> symbol Subshell <*> (Literal.TextElement <$> source)
<|> makeTerm <$> symbol String <*> (Literal.TextElement <$> source)
<|> string
<|> symbol'
<|> makeTerm <$> symbol Character <*> (Literal.Character <$> source)
<|> makeTerm <$> symbol ChainedString <*> children (many (makeTerm <$> symbol String <*> (Literal.TextElement <$> source)))
<|> makeTerm <$> symbol Regex <*> (Literal.Regex <$> source)
<|> makeTerm <$> (symbol Symbol <|> symbol Symbol') <*> (Literal.Symbol <$> source)
where
string :: Assignment Term
string = makeTerm' <$> (symbol String <|> symbol BareString) <*>
(children (inject . Literal.String <$> some interpolation) <|> inject . Literal.TextElement <$> source)
symbol' :: Assignment Term
symbol' = makeTerm' <$> (symbol Symbol <|> symbol Symbol' <|> symbol BareSymbol) <*>
(children (inject . Literal.Symbol <$> some interpolation) <|> inject . Literal.SymbolElement <$> source)
interpolation :: Assignment Term
interpolation = makeTerm <$> symbol Interpolation <*> children (Literal.InterpolationElement <$> expression)
heredoc :: Assignment Term
heredoc = makeTerm <$> symbol HeredocBeginning <*> (Literal.TextElement <$> source)
<|> makeTerm <$> symbol HeredocEnd <*> (Literal.TextElement <$> source)
<|> makeTerm <$> symbol HeredocBody <*> children (some (interpolation <|> heredocEnd))
where heredocEnd = makeTerm <$> symbol HeredocEnd <*> (Literal.TextElement <$> source)
beginBlock :: Assignment Term
beginBlock = makeTerm <$> symbol BeginBlock <*> children (Statement.ScopeEntry <$> many expression)

View File

@ -78,7 +78,7 @@ doRequire :: ( AbstractValue address value effects
, Member (Modules address) effects
)
=> M.ModulePath
-> Evaluator address value effects (Environment address, value)
-> Evaluator address value effects (Bindings address, value)
doRequire path = do
result <- lookupModule path
case result of
@ -135,7 +135,7 @@ instance Evaluatable Class where
super <- traverse subtermAddress classSuperClass
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm classIdentifier))
rvalBox =<< letrec' name (\addr ->
subtermValue classBody <* makeNamespace name addr super)
makeNamespace name addr super (void (subtermAddress classBody)))
data Module a = Module { moduleIdentifier :: !a, moduleStatements :: ![a] }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)
@ -148,7 +148,7 @@ instance Evaluatable Module where
eval (Module iden xs) = do
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm iden))
rvalBox =<< letrec' name (\addr ->
value =<< (eval xs <* makeNamespace name addr Nothing))
makeNamespace name addr Nothing (void (eval xs)))
data LowPrecedenceAnd a = LowPrecedenceAnd { lhs :: a, rhs :: a }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Ord, Show, ToJSONFields1, Traversable, Named1, Message1)

View File

@ -167,7 +167,5 @@ evalRequire :: ( AbstractValue address value effects
=> M.ModulePath
-> Name
-> Evaluator address value effects value
evalRequire modulePath alias = letrec' alias $ \addr -> do
importedEnv <- fst <$> require modulePath
bindAll importedEnv
unit <$ makeNamespace alias addr Nothing
evalRequire modulePath alias = letrec' alias $ \addr ->
unit <$ makeNamespace alias addr Nothing (bindAll . fst =<< require modulePath)

View File

@ -25,13 +25,13 @@ instance Show1 Import where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Import where
eval (Import symbols importPath) = do
modulePath <- resolveWithNodejsStrategy importPath typescriptExtensions
importedEnv <- fst <$> require modulePath
bindAll (renamed importedEnv)
importedBinds <- fst <$> require modulePath
bindAll (renamed importedBinds)
rvalBox unit
where
renamed importedEnv
| Prologue.null symbols = importedEnv
| otherwise = Env.overwrite (toTuple <$> symbols) importedEnv
renamed importedBinds
| Prologue.null symbols = importedBinds
| otherwise = Env.aliasBindings (toTuple <$> symbols) importedBinds
data QualifiedAliasedImport a = QualifiedAliasedImport { qualifiedAliasedImportAlias :: !a, qualifiedAliasedImportFrom :: ImportPath }
deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, Message1, Named1, Ord, Show, ToJSONFields1, Traversable)
@ -92,10 +92,10 @@ instance Show1 QualifiedExportFrom where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable QualifiedExportFrom where
eval (QualifiedExportFrom importPath exportSymbols) = do
modulePath <- resolveWithNodejsStrategy importPath typescriptExtensions
importedEnv <- fst <$> require modulePath
importedBinds <- fst <$> require modulePath
-- Look up addresses in importedEnv and insert the aliases with addresses into the exports.
for_ exportSymbols $ \Alias{..} -> do
let address = Env.lookup aliasValue importedEnv
let address = Env.lookup aliasValue importedBinds
maybe (throwEvalError $ ExportError modulePath aliasValue) (export aliasValue aliasName . Just) address
rvalBox unit
@ -492,7 +492,7 @@ instance Evaluatable Module where
eval (Module iden xs) = do
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm iden))
rvalBox =<< letrec' name (\addr ->
value =<< (eval xs <* makeNamespace name addr Nothing))
makeNamespace name addr Nothing (void (eval xs)))
data InternalModule a = InternalModule { internalModuleIdentifier :: !a, internalModuleStatements :: ![a] }
@ -506,7 +506,7 @@ instance Evaluatable InternalModule where
eval (InternalModule iden xs) = do
name <- maybeM (throwEvalError NoNameError) (declaredName (subterm iden))
rvalBox =<< letrec' name (\addr ->
value =<< (eval xs <* makeNamespace name addr Nothing))
makeNamespace name addr Nothing (void (eval xs)))
instance Declarations a => Declarations (InternalModule a) where
declaredName InternalModule{..} = declaredName internalModuleIdentifier

View File

@ -58,7 +58,7 @@ runParser parser blobSource = unsafeUseAsCStringLen (sourceBytes blobSource) $
-- | Parse 'Source' with the given 'TS.Language' and return its AST.
-- Returns Nothing if the operation timed out.
parseToAST :: (Bounded grammar, Enum grammar, Member (Lift IO) effects, Member Trace effects, Effects effects) => Timeout -> Ptr TS.Language -> Blob -> Eff effects (Maybe (AST [] grammar))
parseToAST :: (Bounded grammar, Enum grammar, Member (Lift IO) effects, Member Trace effects, PureEffects effects) => Timeout -> Ptr TS.Language -> Blob -> Eff effects (Maybe (AST [] grammar))
parseToAST (Milliseconds s) language Blob{..} = bracket TS.ts_parser_new TS.ts_parser_delete $ \ parser -> do
let parserTimeout = s * 1000

View File

@ -1,6 +1,7 @@
{-# LANGUAGE ConstraintKinds, GADTs, RankNTypes, ScopedTypeVariables #-}
module Semantic.Diff
( runDiff
, runPythonDiff
, runRubyDiff
, runTypeScriptDiff
, runJSONDiff
@ -27,6 +28,7 @@ import Serializing.Format
import qualified Language.TypeScript.Assignment as TypeScript
import qualified Language.Ruby.Assignment as Ruby
import qualified Language.JSON.Assignment as JSON
import qualified Language.Python.Assignment as Python
runDiff :: (Member Distribute effs, Member (Exc SomeException) effs, Member (Lift IO) effs, Member Task effs, Member Telemetry effs) => DiffRenderer output -> [BlobPair] -> Eff effs Builder
runDiff ToCDiffRenderer = withParsedBlobPairs (decorate . declarationAlgebra) (render . renderToCDiff) >=> serialize JSON
@ -57,6 +59,17 @@ runTypeScriptDiff = flip distributeFor (\ (blobs :: BlobPair) -> do
diff <$ writeStat (Stat.count "diff.nodes" (bilength diff) languageTag)
where languageTag = languageTagForBlobPair blobs
runPythonDiff :: (Member Telemetry effs, Member (Lift IO) effs, Member Distribute effs, Member Task effs) => [BlobPair] -> Eff effs [Diff (Sum Python.Syntax) () ()]
runPythonDiff = flip distributeFor (\ (blobs :: BlobPair) -> do
terms <- distributeFor blobs (parse pythonParser)
diffs <- diffTerms blobs terms
pure (bimap (const ()) (const ()) diffs))
where
diffTerms blobs terms = time "diff" languageTag $ do
diff <- diff (runJoin terms)
diff <$ writeStat (Stat.count "diff.nodes" (bilength diff) languageTag)
where languageTag = languageTagForBlobPair blobs
runJSONDiff :: (Member Telemetry effs, Member (Lift IO) effs, Member Distribute effs, Member Task effs) => [BlobPair] -> Eff effs [Diff (Sum JSON.Syntax) () ()]
runJSONDiff = flip distributeFor (\ (blobs :: BlobPair) -> do
terms <- distributeFor blobs (parse jsonParser)

View File

@ -35,6 +35,7 @@ distributeFoldMap toTask inputs = fmap fold (distribute (fmap toTask inputs))
-- | Distribute effects run tasks concurrently.
newtype Distribute task output = Distribute (task output)
instance PureEffect Distribute
instance Effect Distribute where
handleState c dist (Request (Distribute task) k) = Request (Distribute (dist (task <$ c))) (dist . fmap k)

View File

@ -3,6 +3,8 @@ module Semantic.Graph
( runGraph
, runCallGraph
, runImportGraph
, runImportGraphToModules
, runImportGraphToModuleInfos
, GraphType(..)
, Graph
, Vertex
@ -60,11 +62,11 @@ runGraph :: forall effs. (Member Distribute effs, Member (Exc SomeException) eff
runGraph ImportGraph _ project
| SomeAnalysisParser parser lang <- someAnalysisParser (Proxy :: Proxy AnalysisClasses) (projectLanguage project) = do
package <- parsePackage parser project
fmap (Graph.moduleVertex . moduleInfo) <$> runImportGraph lang package
runImportGraphToModuleInfos lang package
runGraph CallGraph includePackages project
| SomeAnalysisParser parser lang <- someAnalysisParser (Proxy :: Proxy AnalysisClasses) (projectLanguage project) = do
package <- parsePackage parser project
modules <- topologicalSort <$> runImportGraph lang package
modules <- topologicalSort <$> runImportGraphToModules lang package
runCallGraph lang includePackages modules package
runCallGraph :: ( HasField fields Span
@ -94,7 +96,7 @@ runCallGraph lang includePackages modules package = do
extractGraph (graph, _) = simplify graph
runGraphAnalysis
= runTermEvaluator @_ @(Hole (Maybe Name) (Located Monovariant)) @Abstract
. graphing
. graphing @_ @_ @(Maybe Name) @Monovariant
. caching
. runState (lowerBound @(Heap (Hole (Maybe Name) (Located Monovariant)) All Abstract))
. runFresh 0
@ -108,13 +110,27 @@ runCallGraph lang includePackages modules package = do
. runReader (lowerBound @Span)
. runReader (lowerBound @Vertex)
. providingLiveSet
. runReader (lowerBound @(ModuleTable (NonEmpty (Module (Environment (Hole (Maybe Name) (Located Monovariant)), Hole (Maybe Name) (Located Monovariant))))))
. runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult (Hole (Maybe Name) (Located Monovariant)))))))
. raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
extractGraph <$> runEvaluator (runGraphAnalysis (evaluate lang analyzeModule analyzeTerm modules))
runImportGraphToModuleInfos :: forall effs lang term.
( Declarations term
, Evaluatable (Base term)
, FreeVariables term
, HasPrelude lang
, HasPostlude lang
, Member Trace effs
, Recursive term
, Effects effs
)
=> Proxy lang
-> Package term
-> Eff effs (Graph Vertex)
runImportGraphToModuleInfos lang (package :: Package term) = runImportGraph lang package allModuleInfos
where allModuleInfos info = maybe (vertex (unknownModuleVertex info)) (foldMap (vertex . moduleVertex . moduleInfo)) (ModuleTable.lookup (modulePath info) (packageModules package))
runImportGraph :: forall effs lang term.
runImportGraphToModules :: forall effs lang term.
( Declarations term
, Evaluatable (Base term)
, FreeVariables term
@ -127,14 +143,26 @@ runImportGraph :: forall effs lang term.
=> Proxy lang
-> Package term
-> Eff effs (Graph (Module term))
runImportGraph lang (package :: Package term)
-- Optimization for the common (when debugging) case of one-and-only-one module.
| [m :| []] <- toList (packageModules package) = vertex m <$ trace ("single module, skipping import graph computation for " <> modulePath (moduleInfo m))
| otherwise =
runImportGraphToModules lang (package :: Package term) = runImportGraph lang package resolveOrLowerBound
where resolveOrLowerBound info = maybe lowerBound (foldMap vertex) (ModuleTable.lookup (modulePath info) (packageModules package))
runImportGraph :: forall effs lang term vertex.
( Declarations term
, Evaluatable (Base term)
, FreeVariables term
, HasPrelude lang
, HasPostlude lang
, Member Trace effs
, Recursive term
, Effects effs
)
=> Proxy lang
-> Package term
-> (ModuleInfo -> Graph vertex)
-> Eff effs (Graph vertex)
runImportGraph lang (package :: Package term) f =
let analyzeModule = graphingModuleInfo
extractGraph (_, (graph, _)) = do
info <- graph
maybe lowerBound (foldMap vertex) (ModuleTable.lookup (modulePath info) (packageModules package))
extractGraph (_, (graph, _)) = graph >>= f
runImportGraphAnalysis
= runState lowerBound
. runFresh 0
@ -157,12 +185,13 @@ newtype ImportGraphEff term address outerEffects a = ImportGraphEff
{ runImportGraphEff :: Eff ( Exc (LoopControl address)
': Exc (Return address)
': Env address
': Deref address (Value address (ImportGraphEff term address outerEffects))
': Allocator address (Value address (ImportGraphEff term address outerEffects))
': Reader ModuleInfo
': Reader Span
': Reader PackageInfo
': Modules address
': Reader (ModuleTable (NonEmpty (Module (Environment address, address))))
': Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))
': State (Graph ModuleInfo)
': Resumable (ValueError address (ImportGraphEff term address outerEffects))
': Resumable (AddressError address (Value address (ImportGraphEff term address outerEffects)))

View File

@ -220,6 +220,7 @@ data Files (m :: * -> *) out where
FindFiles :: FilePath -> [String] -> [FilePath] -> Files m [FilePath]
Write :: Destination -> B.Builder -> Files m ()
instance PureEffect Files
instance Effect Files where
handleState c dist (Request (Read source) k) = Request (Read source) (dist . (<$ c) . k)
handleState c dist (Request (ReadProject rootDir dir language excludeDirs) k) = Request (ReadProject rootDir dir language excludeDirs) (dist . (<$ c) . k)
@ -227,7 +228,7 @@ instance Effect Files where
handleState c dist (Request (Write destination builder) k) = Request (Write destination builder) (dist . (<$ c) . k)
-- | Run a 'Files' effect in 'IO'.
runFiles :: (Member (Exc SomeException) effs, Member (Lift IO) effs, Effects effs) => Eff (Files ': effs) a -> Eff effs a
runFiles :: (Member (Exc SomeException) effs, Member (Lift IO) effs, PureEffects effs) => Eff (Files ': effs) a -> Eff effs a
runFiles = interpret $ \ files -> case files of
Read (FromPath path) -> rethrowing (readBlobFromPath path)
Read (FromHandle handle) -> rethrowing (readBlobsFromHandle handle)

View File

@ -1,6 +1,7 @@
{-# LANGUAGE GADTs, RankNTypes #-}
module Semantic.Parse
( runParse
, runPythonParse
, runRubyParse
, runTypeScriptParse
, runJSONParse
@ -24,6 +25,7 @@ import Serializing.Format
import qualified Language.Ruby.Assignment as Ruby
import qualified Language.TypeScript.Assignment as TypeScript
import qualified Language.JSON.Assignment as JSON
import qualified Language.Python.Assignment as Python
runParse :: (Member Distribute effs, Member (Exc SomeException) effs, Member Task effs) => TermRenderer output -> [Blob] -> Eff effs Builder
runParse JSONTermRenderer = withParsedBlobs (render . renderJSONTerm) >=> serialize JSON
@ -42,6 +44,11 @@ runTypeScriptParse = flip distributeFor (\ blob -> do
term <- parse typescriptParser blob
pure (() <$ term))
runPythonParse :: (Member Distribute effs, Member Task effs) => [Blob] -> Eff effs [Term (Sum Python.Syntax) ()]
runPythonParse = flip distributeFor (\ blob -> do
term <- parse pythonParser blob
pure (() <$ term))
runJSONParse :: (Member Distribute effs, Member Task effs) => [Blob] -> Eff effs [Term (Sum JSON.Syntax) ()]
runJSONParse = flip distributeFor (\ blob -> do
term <- parse jsonParser blob

View File

@ -44,11 +44,12 @@ data Resolution (m :: * -> *) output where
NodeJSResolution :: FilePath -> Text -> [FilePath] -> Resolution m (Map FilePath FilePath)
NoResolution :: Resolution m (Map FilePath FilePath)
instance PureEffect Resolution
instance Effect Resolution where
handleState c dist (Request (NodeJSResolution path key paths) k) = Request (NodeJSResolution path key paths) (dist . (<$ c) . k)
handleState c dist (Request NoResolution k) = Request NoResolution (dist . (<$ c) . k)
runResolution :: (Member Files effs, Effects effs) => Eff (Resolution ': effs) a -> Eff effs a
runResolution :: (Member Files effs, PureEffects effs) => Eff (Resolution ': effs) a -> Eff effs a
runResolution = interpret $ \ res -> case res of
NodeJSResolution dir prop excludeDirs -> nodeJSResolutionMap dir prop excludeDirs
NoResolution -> pure Map.empty

View File

@ -154,7 +154,7 @@ runTaskWithConfig options logger statter task = do
queueStat statter stat
pure result
runTraceInTelemetry :: (Member Telemetry effects, Effects effects) => Eff (Trace ': effects) a -> Eff effects a
runTraceInTelemetry :: (Member Telemetry effects, PureEffects effects) => Eff (Trace ': effects) a -> Eff effects a
runTraceInTelemetry = interpret (\ (Trace str) -> writeLog Debug str [])
@ -167,6 +167,7 @@ data Task (m :: * -> *) output where
Render :: Renderer input output -> input -> Task m output
Serialize :: Format input -> input -> Task m Builder
instance PureEffect Task
instance Effect Task where
handleState c dist (Request (Parse parser blob) k) = Request (Parse parser blob) (dist . (<$ c) . k)
handleState c dist (Request (Analyze run analysis) k) = Request (Analyze run analysis) (dist . (<$ c) . k)
@ -176,7 +177,7 @@ instance Effect Task where
handleState c dist (Request (Serialize format input) k) = Request (Serialize format input) (dist . (<$ c) . k)
-- | Run a 'Task' effect by performing the actions in 'IO'.
runTaskF :: (Member (Exc SomeException) effs, Member (Lift IO) effs, Member (Reader Config) effs, Member Telemetry effs, Member Trace effs, Effects effs) => Eff (Task ': effs) a -> Eff effs a
runTaskF :: (Member (Exc SomeException) effs, Member (Lift IO) effs, Member (Reader Config) effs, Member Telemetry effs, Member Trace effs, PureEffects effs) => Eff (Task ': effs) a -> Eff effs a
runTaskF = interpret $ \ task -> case task of
Parse parser blob -> runParser blob parser
Analyze interpret analysis -> pure (interpret analysis)
@ -197,7 +198,7 @@ data ParserCancelled = ParserTimedOut deriving (Show, Typeable)
instance Exception ParserCancelled
-- | Parse a 'Blob' in 'IO'.
runParser :: (Member (Exc SomeException) effs, Member (Lift IO) effs, Member (Reader Config) effs, Member Telemetry effs, Member Trace effs, Effects effs) => Blob -> Parser term -> Eff effs term
runParser :: (Member (Exc SomeException) effs, Member (Lift IO) effs, Member (Reader Config) effs, Member Telemetry effs, Member Trace effs, PureEffects effs) => Blob -> Parser term -> Eff effs term
runParser blob@Blob{..} parser = case parser of
ASTParser language ->
time "parse.tree_sitter_ast_parse" languageTag $ do
@ -227,7 +228,7 @@ runParser blob@Blob{..} parser = case parser of
, Member (Reader Config) effs
, Member Telemetry effs
, Member Trace effs
, Effects effs
, PureEffects effs
)
=> (Source -> assignment (Term (Sum syntaxes) (Record Assignment.Location)) -> ast -> Either (Error.Error String) (Term (Sum syntaxes) (Record Assignment.Location)))
-> Parser ast

View File

@ -133,18 +133,19 @@ data Telemetry (m :: * -> *) output where
WriteStat :: Stat -> Telemetry m ()
WriteLog :: Level -> String -> [(String, String)] -> Telemetry m ()
instance PureEffect Telemetry
instance Effect Telemetry where
handleState c dist (Request (WriteStat stat) k) = Request (WriteStat stat) (dist . (<$ c) . k)
handleState c dist (Request (WriteLog level message pairs) k) = Request (WriteLog level message pairs) (dist . (<$ c) . k)
-- | Run a 'Telemetry' effect by expecting a 'Reader' of 'Queue's to write stats and logs to.
runTelemetry :: (Member (Lift IO) effects, Effects effects) => LogQueue -> StatQueue -> Eff (Telemetry ': effects) a -> Eff effects a
runTelemetry :: (Member (Lift IO) effects, PureEffects effects) => LogQueue -> StatQueue -> Eff (Telemetry ': effects) a -> Eff effects a
runTelemetry logger statter = interpret (\ t -> case t of
WriteStat stat -> queueStat statter stat
WriteLog level message pairs -> queueLogMessage logger level message pairs)
-- | Run a 'Telemetry' effect by ignoring statting/logging.
ignoreTelemetry :: Effects effs => Eff (Telemetry ': effs) a -> Eff effs a
ignoreTelemetry :: PureEffects effs => Eff (Telemetry ': effs) a -> Eff effs a
ignoreTelemetry = interpret (\ t -> case t of
WriteStat{} -> pure ()
WriteLog{} -> pure ())

View File

@ -56,10 +56,11 @@ newtype UtilEff address a = UtilEff
{ runUtilEff :: Eff '[ Exc (LoopControl address)
, Exc (Return address)
, Env address
, Deref address (Value address (UtilEff address))
, Allocator address (Value address (UtilEff address))
, Reader ModuleInfo
, Modules address
, Reader (ModuleTable (NonEmpty (Module (Environment address, address))))
, Reader (ModuleTable (NonEmpty (Module (ModuleResult address))))
, Reader Span
, Reader PackageInfo
, Resumable (ValueError address (UtilEff address))
@ -105,7 +106,7 @@ typecheckGoFile = checking <=< evaluateProjectWithCaching (Proxy :: Proxy 'Langu
callGraphProject parser proxy lang opts paths = runTaskWithOptions opts $ do
blobs <- catMaybes <$> traverse readFile (flip File lang <$> paths)
package <- parsePackage parser (Project (takeDirectory (maybe "/" fst (uncons paths))) blobs lang [])
modules <- topologicalSort <$> runImportGraph proxy package
modules <- topologicalSort <$> runImportGraphToModules proxy package
x <- runCallGraph proxy False modules package
pure (x, (() <$) <$> modules)
@ -120,12 +121,12 @@ data TaskConfig = TaskConfig Config LogQueue StatQueue
evaluateProject' (TaskConfig config logger statter) proxy parser lang paths = either (die . displayException) pure <=< runTaskWithConfig config logger statter $ do
blobs <- catMaybes <$> traverse readFile (flip File lang <$> paths)
package <- fmap quieterm <$> parsePackage parser (Project (takeDirectory (maybe "/" fst (uncons paths))) blobs lang [])
modules <- topologicalSort <$> runImportGraph proxy package
modules <- topologicalSort <$> runImportGraphToModules proxy package
trace $ "evaluating with load order: " <> show (map (modulePath . moduleInfo) modules)
pure (runTermEvaluator @_ @_ @(Value Precise (UtilEff Precise))
(runReader (packageInfo package)
(runReader (lowerBound @Span)
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (Environment Precise, Precise)))))
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Precise)))))
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
(evaluate proxy id withTermSpans modules))))))
@ -133,10 +134,10 @@ evaluateProject' (TaskConfig config logger statter) proxy parser lang paths = ei
evaluateProjectWithCaching proxy parser lang path = runTaskWithOptions debugOptions $ do
project <- readProject Nothing path lang []
package <- fmap quieterm <$> parsePackage parser project
modules <- topologicalSort <$> runImportGraph proxy package
modules <- topologicalSort <$> runImportGraphToModules proxy package
pure (runReader (packageInfo package)
(runReader (lowerBound @Span)
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (Environment Monovariant, Monovariant)))))
(runReader (lowerBound @(ModuleTable (NonEmpty (Module (ModuleResult Monovariant)))))
(raiseHandler (runModules (ModuleTable.modulePaths (packageModules package)))
(evaluate proxy id withTermSpans modules)))))

View File

@ -16,7 +16,7 @@ spec config = parallel $ do
case ModuleTable.lookup "main.go" <$> res of
Right (Just (Module _ (env, addr) :| [])) -> do
Env.names env `shouldBe` [ "Bar", "Rab", "foo", "main" ]
(derefQName heap ("foo" :| []) env >>= deNamespace) `shouldBe` Just ("foo", ["New"])
(derefQName heap ("foo" :| []) env >>= deNamespace heap) `shouldBe` Just ("foo", ["New"])
other -> expectationFailure (show other)
it "imports with aliases (and side effects only)" $ do
@ -24,7 +24,7 @@ spec config = parallel $ do
case ModuleTable.lookup "main1.go" <$> res of
Right (Just (Module _ (env, addr) :| [])) -> do
Env.names env `shouldBe` [ "f", "main" ]
(derefQName heap ("f" :| []) env >>= deNamespace) `shouldBe` Just ("f", ["New"])
(derefQName heap ("f" :| []) env >>= deNamespace heap) `shouldBe` Just ("f", ["New"])
other -> expectationFailure (show other)
where

View File

@ -34,9 +34,9 @@ spec config = parallel $ do
Right (Just (Module _ (env, addr) :| [])) -> do
Env.names env `shouldBe` [ "Foo", "NS1" ]
(derefQName heap ("NS1" :| []) env >>= deNamespace) `shouldBe` Just ("NS1", ["Sub1", "b", "c"])
(derefQName heap ("NS1" :| ["Sub1"]) env >>= deNamespace) `shouldBe` Just ("Sub1", ["Sub2"])
(derefQName heap ("NS1" :| ["Sub1", "Sub2"]) env >>= deNamespace) `shouldBe` Just ("Sub2", ["f"])
(derefQName heap ("NS1" :| []) env >>= deNamespace heap) `shouldBe` Just ("NS1", ["Sub1", "b", "c"])
(derefQName heap ("NS1" :| ["Sub1"]) env >>= deNamespace heap) `shouldBe` Just ("Sub1", ["Sub2"])
(derefQName heap ("NS1" :| ["Sub1", "Sub2"]) env >>= deNamespace heap) `shouldBe` Just ("Sub2", ["f"])
other -> expectationFailure (show other)
where

View File

@ -19,9 +19,9 @@ spec config = parallel $ do
Right (Just (Module _ (env, addr) :| [])) -> do
Env.names env `shouldContain` [ "a", "b" ]
(derefQName heap ("a" :| []) env >>= deNamespace) `shouldBe` Just ("a", ["foo"])
(derefQName heap ("b" :| []) env >>= deNamespace) `shouldBe` Just ("b", ["c"])
(derefQName heap ("b" :| ["c"]) env >>= deNamespace) `shouldBe` Just ("c", ["baz"])
(derefQName heap ("a" :| []) env >>= deNamespace heap) `shouldBe` Just ("a", ["foo"])
(derefQName heap ("b" :| []) env >>= deNamespace heap) `shouldBe` Just ("b", ["c"])
(derefQName heap ("b" :| ["c"]) env >>= deNamespace heap) `shouldBe` Just ("c", ["baz"])
other -> expectationFailure (show other)
it "imports with aliases" $ do
@ -41,7 +41,7 @@ spec config = parallel $ do
case ModuleTable.lookup "main3.py" <$> res of
Right (Just (Module _ (env, addr) :| [])) -> do
Env.names env `shouldContain` [ "utils" ]
(derefQName heap ("utils" :| []) env >>= deNamespace) `shouldBe` Just ("utils", ["to_s"])
(derefQName heap ("utils" :| []) env >>= deNamespace heap) `shouldBe` Just ("utils", ["to_s"])
other -> expectationFailure (show other)
it "subclasses" $ do

View File

@ -45,7 +45,7 @@ spec config = parallel $ do
heapLookupAll addr heap `shouldBe` Just [String "\"<bar>\""]
Env.names env `shouldContain` [ "Bar", "Foo" ]
(derefQName heap ("Bar" :| []) env >>= deNamespace) `shouldBe` Just ("Bar", ["baz", "foo", "inspect"])
(derefQName heap ("Bar" :| []) env >>= deNamespace heap) `shouldBe` Just ("Bar", ["baz", "inspect", "foo"])
other -> expectationFailure (show other)
it "evaluates modules" $ do

View File

@ -26,8 +26,8 @@ spec config = parallel $ do
Right (Just (Module _ (env, _) :| [])) -> do
Env.names env `shouldBe` [ "b", "z" ]
(derefQName heap ("b" :| []) env >>= deNamespace) `shouldBe` Just ("b", [ "baz", "foo" ])
(derefQName heap ("z" :| []) env >>= deNamespace) `shouldBe` Just ("z", [ "baz", "foo" ])
(derefQName heap ("b" :| []) env >>= deNamespace heap) `shouldBe` Just ("b", [ "baz", "foo" ])
(derefQName heap ("z" :| []) env >>= deNamespace heap) `shouldBe` Just ("z", [ "baz", "foo" ])
other -> expectationFailure (show other)
it "side effect only imports" $ do

View File

@ -37,6 +37,7 @@ evaluate
. runValueError
. runEnvironmentError
. runAddressError
. runDeref
. runAllocator @Precise @_ @Val
. (>>= deref . snd)
. runEnv lowerBound
@ -52,6 +53,7 @@ newtype SpecEff a = SpecEff
, Exc (Return Precise)
, Env Precise
, Allocator Precise Val
, Deref Precise Val
, Resumable (AddressError Precise Val)
, Resumable (EnvironmentError Precise)
, Resumable (ValueError Precise SpecEff)

View File

@ -53,6 +53,7 @@ import qualified Data.Syntax.Directive as Directive
import qualified Data.Syntax.Statement as Statement
import qualified Data.Syntax.Expression as Expression
import qualified Language.Ruby.Syntax as Ruby.Syntax
import qualified Language.Python.Syntax as Python.Syntax
import qualified Data.Abstract.Name as Name
import Data.Term
import Data.Text as T (Text, pack)
@ -280,6 +281,12 @@ instance Listable1 Literal.Null where
instance Listable1 Literal.TextElement where
liftTiers tiers = cons1 Literal.TextElement
instance Listable1 Literal.InterpolationElement where
liftTiers tiers = liftCons1 tiers Literal.InterpolationElement
instance Listable1 Literal.Character where
liftTiers tiers = cons1 Literal.Character
instance Listable1 Statement.Statements where
liftTiers tiers = liftCons1 (liftTiers tiers) Statement.Statements
@ -410,7 +417,10 @@ instance Listable1 Literal.String where
liftTiers tiers = liftCons1 (liftTiers tiers) Literal.String
instance Listable1 Literal.Symbol where
liftTiers tiers = cons1 Literal.Symbol
liftTiers tiers = liftCons1 (liftTiers tiers) Literal.Symbol
instance Listable1 Literal.SymbolElement where
liftTiers tiers = cons1 Literal.SymbolElement
instance Listable1 Statement.Assignment where
liftTiers tiers = liftCons3 (liftTiers tiers) tiers tiers Statement.Assignment
@ -478,6 +488,15 @@ instance Listable1 Ruby.Syntax.Require where
instance Listable1 Ruby.Syntax.Send where
liftTiers tiers = liftCons4 (liftTiers tiers) (liftTiers tiers) (liftTiers tiers) (liftTiers tiers) Ruby.Syntax.Send
instance Listable Python.Syntax.QualifiedName where
tiers = liftCons1 tiers1 Python.Syntax.QualifiedName \/ liftCons2 tiers tiers1 Python.Syntax.RelativeQualifiedName
instance Listable1 Python.Syntax.Import where
liftTiers tiers = cons2 Python.Syntax.Import
instance Listable Python.Syntax.Alias where
tiers = cons2 Python.Syntax.Alias
type ListableSyntax = Sum
'[ Comment.Comment

View File

@ -23,7 +23,7 @@ callGraphPythonProject paths = runTaskWithOptions defaultOptions $ do
let lang = Language.Python
blobs <- catMaybes <$> traverse readFile (flip File lang <$> paths)
package <- parsePackage pythonParser (Project (takeDirectory (maybe "/" fst (uncons paths))) blobs lang [])
modules <- topologicalSort <$> runImportGraph proxy package
modules <- topologicalSort <$> runImportGraphToModules proxy package
runCallGraph proxy False modules package
spec :: Spec

View File

@ -19,6 +19,7 @@ import Data.Diff (Diff)
import Data.Sum
import Language.Ruby.Assignment (Syntax)
import qualified Language.Ruby.Assignment as Ruby
import qualified Language.Python.Syntax as Python
import Data.Functor.Classes
import qualified Data.Syntax.Expression as Expression

View File

@ -30,7 +30,7 @@ import Data.Abstract.Heap as X
import Data.Abstract.Module as X
import Data.Abstract.ModuleTable as X hiding (lookup)
import Data.Abstract.Name as X
import Data.Abstract.Value.Concrete (Value(..), ValueError, runValueError)
import Data.Abstract.Value.Concrete (Value(..), ValueError, runValueError, materializeEnvironment)
import Data.Bifunctor (first)
import Data.Blob as X
import Data.ByteString.Builder (toLazyByteString)
@ -116,12 +116,12 @@ type TestEvaluatingErrors = '[ ValueError Precise (UtilEff Precise)
, Unspecialized Val
, LoadError Precise
]
testEvaluating :: Evaluator Precise Val TestEvaluatingEffects (ModuleTable (NonEmpty (Module (Environment Precise, Precise))))
testEvaluating :: Evaluator Precise Val TestEvaluatingEffects (ModuleTable (NonEmpty (Module (ModuleResult Precise))))
-> IO
( [String]
, ( Heap Precise Latest Val
, Either (SomeExc (Data.Sum.Sum TestEvaluatingErrors))
(ModuleTable (NonEmpty (Module (Environment Precise, Precise))))
(ModuleTable (NonEmpty (Module (ModuleResult Precise))))
)
)
testEvaluating
@ -142,19 +142,31 @@ testEvaluating
type Val = Value Precise (UtilEff Precise)
deNamespace :: Value Precise term -> Maybe (Name, [Name])
deNamespace (Namespace name scope) = Just (name, Env.names scope)
deNamespace _ = Nothing
deNamespace :: Heap Precise (Cell Precise) (Value Precise term)
-> Value Precise term
-> Maybe (Name, [Name])
deNamespace heap ns@(Namespace name _ _) = (,) name . Env.allNames <$> namespaceScope heap ns
deNamespace _ _ = Nothing
namespaceScope :: Value Precise term -> Maybe (Environment Precise)
namespaceScope (Namespace _ scope) = Just scope
namespaceScope _ = Nothing
namespaceScope :: Heap Precise (Cell Precise) (Value Precise term)
-> Value Precise term
-> Maybe (Environment Precise)
namespaceScope heap ns@(Namespace _ _ _)
= either (const Nothing) snd
. run
. runFresh 0
. runAddressError
. runState heap
. runDeref
$ materializeEnvironment ns
derefQName :: Heap Precise (Cell Precise) (Value Precise term) -> NonEmpty Name -> Environment Precise -> Maybe (Value Precise term)
derefQName heap = go
where go (n1 :| ns) env = Env.lookup n1 env >>= flip heapLookup heap >>= getLast . unLatest >>= case ns of
namespaceScope _ _ = Nothing
derefQName :: Heap Precise (Cell Precise) (Value Precise term) -> NonEmpty Name -> Bindings Precise -> Maybe (Value Precise term)
derefQName heap names binds = go names (Env.newEnv binds)
where go (n1 :| ns) env = Env.lookupEnv' n1 env >>= flip heapLookup heap >>= getLast . unLatest >>= case ns of
[] -> Just
(n2 : ns) -> namespaceScope >=> go (n2 :| ns)
(n2 : ns) -> namespaceScope heap >=> go (n2 :| ns)
newtype Verbatim = Verbatim ByteString
deriving (Eq)

View File

@ -0,0 +1,5 @@
class Dinosaur {
void apply() {
(T1)a[0];
}
}

View File

@ -0,0 +1,5 @@
class Dinosaur {
void apply() {
anArray[2];
}
}

View File

@ -0,0 +1,17 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
{+(Subscript
{+(Identifier)+}
{+(Integer)+})+}
{-(Annotation
{-(Subscript
{-(Identifier)-}
{-(Integer)-})-}
{-(Identifier)-})-})))))

View File

@ -0,0 +1,17 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
{+(Annotation
{+(Subscript
{+(Identifier)+}
{+(Integer)+})+}
{+(Identifier)+})+}
{-(Subscript
{-(Identifier)-}
{-(Integer)-})-})))))

View File

@ -0,0 +1,14 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Annotation
(Subscript
(Identifier)
(Integer))
(Identifier)))))))

View File

@ -0,0 +1,12 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Subscript
(Identifier)
(Integer)))))))

View File

@ -0,0 +1,7 @@
class Dino {
void fn() {
for (File file : snap.index()) {
assert oldFile == null;
}
}
}

View File

@ -0,0 +1,5 @@
class Dino {
void fn() {
assert failure : "expecting non null";
}
}

View File

@ -0,0 +1,25 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
{+(AssertStatement
{+(Identifier)+}
{+(TextElement)+})+}
{-(ForEach
{-(Variable
{-(Identifier)-}
{-(Identifier)-})-}
{-(Call
{-(MemberAccess
{-(Identifier)-})-}
{-(Empty)-})-}
{-(Statements
{-(AssertStatement
{-(Equal
{-(Identifier)-}
{-(Null)-})-})-})-})-})))))

View File

@ -0,0 +1,25 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
{+(ForEach
{+(Variable
{+(Identifier)+}
{+(Identifier)+})+}
{+(Call
{+(MemberAccess
{+(Identifier)+})+}
{+(Empty)+})+}
{+(Statements
{+(AssertStatement
{+(Equal
{+(Identifier)+}
{+(Null)+})+})+})+})+}
{-(AssertStatement
{-(Identifier)-}
{-(TextElement)-})-})))))

View File

@ -0,0 +1,22 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(ForEach
(Variable
(Identifier)
(Identifier))
(Call
(MemberAccess
(Identifier))
(Empty))
(Statements
(AssertStatement
(Equal
(Identifier)
(Null))))))))))

View File

@ -0,0 +1,12 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(AssertStatement
(Identifier)
(TextElement)))))))

View File

@ -0,0 +1,9 @@
a ^ b;
a % b;
a << b;
a >> b;
a >>> b;
3 + 2;
3 - 2;
3 * 2;
9 / 3;

View File

@ -8,12 +8,3 @@ a && b;
a || b;
a & b;
a | b;
a ^ b;
a % b;
a << b;
a >> b;
a >>> b;
3 + 2;
3 - 2;
3 * 2;
9 / 3;

View File

@ -0,0 +1,59 @@
(Statements
{+(GreaterThan
{+(Identifier)+}
{+(Identifier)+})+}
{+(LessThan
{+(Identifier)+}
{+(Identifier)+})+}
{+(Equal
{+(Identifier)+}
{+(Identifier)+})+}
{+(GreaterThanEqual
{+(Identifier)+}
{+(Identifier)+})+}
{+(LessThanEqual
{+(Identifier)+}
{+(Identifier)+})+}
{+(Not
{+(Equal
{+(Identifier)+}
{+(Identifier)+})+})+}
{+(And
{+(Identifier)+}
{+(Identifier)+})+}
{+(Or
{+(Identifier)+}
{+(Identifier)+})+}
{+(BAnd
{+(Identifier)+}
{+(Identifier)+})+}
{+(BOr
{+(Identifier)+}
{+(Identifier)+})+}
{-(BXOr
{-(Identifier)-}
{-(Identifier)-})-}
{-(Modulo
{-(Identifier)-}
{-(Identifier)-})-}
{-(LShift
{-(Identifier)-}
{-(Identifier)-})-}
{-(RShift
{-(Identifier)-}
{-(Identifier)-})-}
{-(UnsignedRShift
{-(Identifier)-}
{-(Identifier)-})-}
{-(Plus
{-(Integer)-}
{-(Integer)-})-}
{-(Minus
{-(Integer)-}
{-(Integer)-})-}
{-(Times
{-(Integer)-}
{-(Integer)-})-}
{-(DividedBy
{-(Integer)-}
{-(Integer)-})-})

View File

@ -0,0 +1,59 @@
(Statements
{+(BXOr
{+(Identifier)+}
{+(Identifier)+})+}
{+(Modulo
{+(Identifier)+}
{+(Identifier)+})+}
{+(LShift
{+(Identifier)+}
{+(Identifier)+})+}
{+(RShift
{+(Identifier)+}
{+(Identifier)+})+}
{+(UnsignedRShift
{+(Identifier)+}
{+(Identifier)+})+}
{+(Plus
{+(Integer)+}
{+(Integer)+})+}
{+(Minus
{+(Integer)+}
{+(Integer)+})+}
{+(Times
{+(Integer)+}
{+(Integer)+})+}
{+(DividedBy
{+(Integer)+}
{+(Integer)+})+}
{-(GreaterThan
{-(Identifier)-}
{-(Identifier)-})-}
{-(LessThan
{-(Identifier)-}
{-(Identifier)-})-}
{-(Equal
{-(Identifier)-}
{-(Identifier)-})-}
{-(GreaterThanEqual
{-(Identifier)-}
{-(Identifier)-})-}
{-(LessThanEqual
{-(Identifier)-}
{-(Identifier)-})-}
{-(Not
{-(Equal
{-(Identifier)-}
{-(Identifier)-})-})-}
{-(And
{-(Identifier)-}
{-(Identifier)-})-}
{-(Or
{-(Identifier)-}
{-(Identifier)-})-}
{-(BAnd
{-(Identifier)-}
{-(Identifier)-})-}
{-(BOr
{-(Identifier)-}
{-(Identifier)-})-})

View File

@ -0,0 +1,28 @@
(Statements
(BXOr
(Identifier)
(Identifier))
(Modulo
(Identifier)
(Identifier))
(LShift
(Identifier)
(Identifier))
(RShift
(Identifier)
(Identifier))
(UnsignedRShift
(Identifier)
(Identifier))
(Plus
(Integer)
(Integer))
(Minus
(Integer)
(Integer))
(Times
(Integer)
(Integer))
(DividedBy
(Integer)
(Integer)))

View File

@ -0,0 +1,32 @@
(Statements
(GreaterThan
(Identifier)
(Identifier))
(LessThan
(Identifier)
(Identifier))
(Equal
(Identifier)
(Identifier))
(GreaterThanEqual
(Identifier)
(Identifier))
(LessThanEqual
(Identifier)
(Identifier))
(Not
(Equal
(Identifier)
(Identifier)))
(And
(Identifier)
(Identifier))
(Or
(Identifier)
(Identifier))
(BAnd
(Identifier)
(Identifier))
(BOr
(Identifier)
(Identifier)))

View File

@ -0,0 +1,5 @@
public class Point {
void dinosaur() {
Boolean example = false;
}
}

View File

@ -0,0 +1,18 @@
(Statements
(Class
(AccessibilityModifier)
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
{ (Identifier)
->(Identifier) })
{ (Boolean)
->(Boolean) })))))))

View File

@ -0,0 +1,18 @@
(Statements
(Class
(AccessibilityModifier)
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
{ (Identifier)
->(Identifier) })
{ (Boolean)
->(Boolean) })))))))

View File

@ -0,0 +1,16 @@
(Statements
(Class
(AccessibilityModifier)
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
(Identifier))
(Boolean))))))))

View File

@ -0,0 +1,16 @@
(Statements
(Class
(AccessibilityModifier)
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
(Identifier))
(Boolean))))))))

7
test/fixtures/java/corpus/Char.B.java vendored Normal file
View File

@ -0,0 +1,7 @@
class Point {
Char dinosaur() {
Char B = 'B';
if (x)
B;
}
}

View File

@ -0,0 +1,23 @@
(Statements
(Class
{-(AccessibilityModifier)-}
(Identifier)
(Statements
(Method
{+(Identifier)+}
{-(Void)-}
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
{ (Identifier)
->(Identifier) })
{ (TextElement)
->(TextElement) }))
{+(If
{+(Identifier)+}
{+(Identifier)+}
{+(Empty)+})+})))))

View File

@ -0,0 +1,23 @@
(Statements
(Class
{+(AccessibilityModifier)+}
(Identifier)
(Statements
(Method
{+(Void)+}
{-(Identifier)-}
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
{ (Identifier)
->(Identifier) })
{ (TextElement)
->(TextElement) }))
{-(If
{-(Identifier)-}
{-(Identifier)-}
{-(Empty)-})-})))))

View File

@ -0,0 +1,16 @@
(Statements
(Class
(AccessibilityModifier)
(Identifier)
(Statements
(Method
(Void)
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
(Identifier))
(TextElement))))))))

View File

@ -0,0 +1,19 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Identifier)
(Empty)
(Identifier)
(Statements
(Statements
(Assignment
(Variable
(Identifier)
(Identifier))
(TextElement)))
(If
(Identifier)
(Identifier)
(Empty)))))))

View File

@ -0,0 +1,3 @@
class Dino {
}

View File

@ -0,0 +1,19 @@
(Statements
(Class
(Identifier)
(Statements
{-(Method
{-(Void)-}
{-(AccessibilityModifier)-}
{-(Empty)-}
{-(Identifier)-}
{-(Statements
{-(Call
{-(MemberAccess
{-(Identifier)-})-}
{-(New
{-(GenericType
{-(Identifier)-}
{-(Identifier)-})-}
{-(Statements)-})-}
{-(Empty)-})-})-})-})))

View File

@ -0,0 +1,19 @@
(Statements
(Class
(Identifier)
(Statements
{+(Method
{+(Void)+}
{+(AccessibilityModifier)+}
{+(Empty)+}
{+(Identifier)+}
{+(Statements
{+(Call
{+(MemberAccess
{+(Identifier)+})+}
{+(New
{+(GenericType
{+(Identifier)+}
{+(Identifier)+})+}
{+(Statements)+})+}
{+(Empty)+})+})+})+})))

View File

@ -0,0 +1,19 @@
(Statements
(Class
(Identifier)
(Statements
(Method
(Void)
(AccessibilityModifier)
(Empty)
(Identifier)
(Statements
(Call
(MemberAccess
(Identifier))
(New
(GenericType
(Identifier)
(Identifier))
(Statements))
(Empty)))))))

View File

@ -0,0 +1,4 @@
(Statements
(Class
(Identifier)
(Statements)))

View File

@ -0,0 +1 @@
// This is a single-line comment.

View File

@ -1,5 +1,3 @@
// This is a single-line comment.
/* This is
a multi-line
comment */

View File

@ -0,0 +1,5 @@
(Statements
(Context
{ (Comment)
->(Comment) }
(Empty)))

View File

@ -0,0 +1,5 @@
(Statements
(Context
{ (Comment)
->(Comment) }
(Empty)))

View File

@ -0,0 +1,4 @@
(Statements
(Context
(Comment)
(Empty)))

View File

@ -0,0 +1,4 @@
(Statements
(Context
(Comment)
(Empty)))

View File

@ -1,8 +1,8 @@
(Statements
(Call
(Identifier)
(Symbol)
(Symbol)
(SymbolElement)
(SymbolElement)
(Empty))
(Call
(Identifier)

View File

@ -6,10 +6,10 @@
(Send
(Identifier))
(KeyValue
(Symbol)
(SymbolElement)
(Integer))
(KeyValue
(Symbol)
(SymbolElement)
(Boolean)))
(Send
(Send

View File

@ -2,10 +2,10 @@
{+(TextElement)+}
{+(TextElement)+}
{+(TextElement)+}
{ (TextElement)
->(TextElement) }
{+(TextElement)+}
{+(TextElement)+}
{+(TextElement)+}
{-(TextElement)-}
{-(TextElement)-}
{-(TextElement)-}
{-(TextElement)-}

View File

@ -4,8 +4,8 @@
{+(TextElement)+}
{+(TextElement)+}
{+(TextElement)+}
{+(TextElement)+}
{-(TextElement)-}
{ (TextElement)
->(TextElement) }
{-(TextElement)-}
{-(TextElement)-}
{-(TextElement)-}

View File

@ -10,8 +10,8 @@
(Send
{ (Identifier)
->(Identifier) })
{ (Symbol)
->(Symbol) })
{ (SymbolElement)
->(SymbolElement) })
{-(Assignment
{-(Subscript
{-(Send

View File

@ -10,8 +10,8 @@
(Send
{ (Identifier)
->(Identifier) })
{ (Symbol)
->(Symbol) })
{ (SymbolElement)
->(SymbolElement) })
{+(Assignment
{+(Subscript
{+(Send

Some files were not shown because too many files have changed in this diff Show More