the assistant approach to automatic programming yishai feldman the interdisciplinary center herzliya
TRANSCRIPT
The Assistant ApproachThe Assistant Approachto Automatic Programmingto Automatic Programming
Yishai Feldman
The Interdisciplinary Center
Herzliya
Programming ActivitiesProgramming Activitiesand Agentsand Agents
Non-accounting Manager
brief, vague requirement
detailed requirement
specification
code
Accounting Expert
System Analyst/Designer
Programmer
Transformational ApproachesTransformational Approaches
specification
implementation
clear efficient
X ** 2 X * X
m min(A)
m for i 1 to size(A) do if A[i] < m then m A[i]
Very High Level LanguagesVery High Level Languagesprev := {}; val := {};
val(x) := {x} ;
(while newnodes {})
n from newnodes;
( m graph {n})
newval := val(n) + cost(n, m);
if val(m) = om or val(m) > newval then
val(m) := newval;
prev(m) := n;
if m y then newnodes with := m; end if;
end if;
end ;
end while;
Natural Language SpecificationNatural Language Specification
“The RATS transmission times are entered into the schedule”
“Each RATS clock transmission times and transmission length is made a component of a new transmission entry which is entered into the transmission schceule”
Problem is informality
Programming by ExampleProgramming by Example
{( ) ( )
(A B) (A)
(A B C D) (A B)
(A B C D E F) (A B C)}
(DEFUN HALF (X)
(H X X))
(DEFUN H (X Y)
(COND ((ATOM Y) NIL)
(T (CONS (CAR X)
(H (CDR X) (CDDR X))))))
Delegating WorkDelegating Workto the Apprenticeto the Apprentice
• Productivity: Delegate routine details
• Reliability: Standardization of common practices
Example: Table-LookupExample: Table-Lookup
function table-lookup(table, key)
bucket table[hash(key)]
loop
if bucket = nil then return nil
entry head(bucket)
if key(entry) = key then return entry
bucket tail(bucket)
Table-DeleteTable-Delete
procedure table-delete(table, key)
index hash(key)
bucket table[index]
if key(head(bucket)) = key
then table[index] tail(bucket)
else bucket-delete(bucket, key)
return table
Bucket-DeleteBucket-Deleteprocedure bucket-delete(bucket, key)
previous bucket
loop
bucket tail(previous)
if bucket = nil then return nil
if key(head(bucket)) = key then
tail(previous) tail(tail(previous))
return nil
previous bucket
Analysis: Table-LookupAnalysis: Table-Lookup
function table-lookup(table, key)
bucket table[hash(key)]
loop
if bucket = nil then return nil
entry head(bucket)
if key(entry) = key then return entry
bucket tail(bucket)
Analysis: Table-LookupAnalysis: Table-Lookup
function table-lookup(table, key)
bucket table[hash(key)]
loop
if bucket = nil then return nil
entry head(bucket)
if key(entry) = key then return entry
bucket tail(bucket)
Analysis: Table-LookupAnalysis: Table-Lookup
function table-lookup(table, key)
bucket table[hash(key)]
loop
if bucket = nil then return nil
entry head(bucket)
if key(entry) = key then return entry
bucket tail(bucket)
Analysis: Bucket-DeleteAnalysis: Bucket-Deleteprocedure bucket-delete(bucket, key)
previous bucket
loop
bucket tail(previous)
if bucket = nil then return nil
if key(head(bucket)) = key then
tail(previous) tail(tail(previous))
return nil
previous bucket
Analysis: Bucket-DeleteAnalysis: Bucket-Deleteprocedure bucket-delete(bucket, key)
previous bucket
loop
bucket tail(previous)
if bucket = nil then return nil
if key(head(bucket)) = key then
tail(previous) tail(tail(previous))
return nil
previous bucket
Analysis: Bucket-DeleteAnalysis: Bucket-Deleteprocedure bucket-delete(bucket, key)
previous bucket
loop
bucket tail(previous)
if bucket = nil then return nil
if key(head(bucket)) = key then
tail(previous) tail(tail(previous))
return nil
previous bucket
Analysis: Bucket-DeleteAnalysis: Bucket-Deleteprocedure bucket-delete(bucket, key)
previous bucket
loop
bucket tail(previous)
if bucket = nil then return nil
if key(head(bucket)) = key then
tail(previous) tail(tail(previous))
return nil
previous bucket
The Plan CalculusThe Plan Calculus
• Wide-spectrum• Canonical• Language independent• Expressive• Convenient for
manipulation
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (PAGE 0) (TITLE {the title}) (DATA {the input structure of the enumerator})) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF ({the empty-test of the enumerator} DATA) (RETURN)) (WHEN (> LINE 63) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3) ({the column-headings} {REPORT, modified} {LINE, modified})) ({the print-item} {REPORT, modified} {LINE, modified} ({the element-accessor of the enumerator} DATA)) (SETQ DATA ({the step of the enumerator} DATA))) ({the summary} {REPORT, modified}))))
s-X Insert a simple-report. <end>
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (PAGE 0) (TITLE "Report of Reaction Timings (in msec.)") (DATA {the input structure of the enumerator})) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF ({the empty-test of the enumerator} DATA) (RETURN)) (WHEN (> LINE 63) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3) ({the column-headings} {REPORT, modified} {LINE, modified})) ({the print-item} {REPORT, modified} {LINE, modified} ({the element-accessor of the enumerator} DATA)) (SETQ DATA ({the step of the enumerator} DATA))) ({the summary} {REPORT, modified}))))
s-N Next Roledirect editing
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (LIST TIMINGS) (PAGE 0) (TITLE "Report of Reaction Timings (in msec.)")) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF (NULL LIST) (RETURN)) (WHEN (> LINE 63) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3) ({the column-headings} {REPORT, modified} {LINE, modified})) ({the print-item} {REPORT, modified} {LINE, modified} {(CAR LIST), the output element}) (SETQ LIST (CDR LIST))) ({the summary} {REPORT, modified}))))
s-X Fill the enumerator with a list-enumeration of TIMINGS.<end>
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (LIST TIMINGS) (PAGE 0) (TITLE "Report of Reaction Timings (in msec.)")) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF (NULL LIST) (RETURN)) (WHEN (> LINE 63) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3)) ({the print-item} {REPORT, modified} {LINE, modified} {(CAR LIST), the output element}) (SETQ LIST (CDR LIST))) ({the summary} {REPORT, modified}))))
s-X Remove the column-headings. <end>
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (LIST TIMINGS) (PAGE 0) (TITLE "Report of Reaction Timings (in msec.)")) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF (NULL LIST) (RETURN)) (WHEN (> LINE 63) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3)) (FORMAT REPORT "~&~5X~8:D" {(CAR LIST), the output element}) (SETQ LINE (+ LINE 1)) (SETQ LIST (CDR LIST))) ({the summary} {REPORT, modified}))))
s-F Fill the print-item with a print-out of "~&~5X~8:D".<end>
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (LIST TIMINGS) (PAGE 0) (TITLE "Report of Reaction Timings (in msec.)")) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF (NULL LIST) (RETURN)) (WHEN (> LINE 63) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3)) (FORMAT REPORT "~&~5X~8:D" {(CAR LIST), the output element}) (SETQ LINE (+ LINE 1)) (SETQ LIST (CDR LIST))) (FORMAT REPORT "~2&~{mean:~8D (deviation: ~:D)~}" (MEAN-AND-DEVIATION TIMINGS)))))
s-W What needs to be done? Fill the summary.s-N s-N direct editing
(DEFUN REPORT-TIMINGS (TIMINGS) (WITH-OPEN-FILE (REPORT "report.txt" ':OUT) (LET* ((DATE (TIME:PRINT-CURRENT-TIME NIL)) (LINE 66) (LIST TIMINGS) (PAGE 0) (TITLE "Report of Reaction Timings (in msec.)")) (FORMAT REPORT "~5%~66:<~A~>~2%~66:<~A~>~%" TITLE DATE) (LOOP DO (IF (NULL LIST) (RETURN)) (WHEN (> LINE 62) (SETQ PAGE (+ PAGE 1)) (FORMAT REPORT "~|~%Page:~3D~50:<~A~>~17A~2%“ PAGE TITLE DATE) (SETQ LINE 3)) (FORMAT REPORT "~&~5X~8:D" (CAR LIST)) (SETQ LINE (+ LINE 1)) (SETQ LIST (CDR LIST))) (FORMAT REPORT "~2&~{mean:~8D (deviation: ~:D)~}" (MEAN-AND-DEVIATION TIMINGS)))))
s-<end> Finish editing the function REPORT-TIMINGS
KBEmacs Example: SummaryKBEmacs Example: Summary
Define a simple report program REPORT-TIMINGS with one parameter, a list of timings. Print the title "Report of Reaction Timings (in msec.)". Print each timing and then print a summary showing the mean and deviation of the timings. Do not print any column headings.
Define a program REPORT-TIMINGS with a parameter TIMINGS.
Insert a simple-report.
Fill the title with "Report of Reaction Timings (in msec.)".
Fill the enumerator with a list-enumeration of TIMINGS.
Remove the column-headings.
Fill the print-item with a print-out of "~&~5X~8:D".
Fill the summary with (FORMAT ... )
KBEmacs Example: ADAKBEmacs Example: ADA
Define a simple report program UNIT_REPAIR_REPORT. Enumerate the chain of repairs associated with a unit record, printing each one. Query the user for the key (UNIT_KEY) of the unit record to start from. Print the title ("Report of Repairs on Unit " & UNIT_KEY). Do not print a summary.
Define a simple_report procedure UNIT_REPAIR_REPORT.
Fill the enumerator with a chain_enumeration of UNITS and REPAIRS.
Fill the main_file_key with a query_user_for_key of UNITS.
Share the first READ and the second READ.
Fill the title with ("Report of Repairs on Unit " & UNIT_KEY)
Remove the summary.
Automated Program RecognitionAutomated Program Recognition
HT-MEMBER is a Set Membership operation.It determines whether or not ELEMENT is an element of the set STRUCTURE.
The Set is implemented as a Hash Table.The Hash Table is implemented as an Array of buckets, indexed by hash code.
The buckets are implemented as Ordered Lists. They are ordered lexicographically. The elements in the buckets are strings. An Ordered List Membership is used to determine whether or not ELEMENT is in the fetched bucket, BUCKET.
(DEFUN HT-MEMBER (STRUCTURE ELEMENT)
(LET ((BUCKET (AREF STRUCTURE (HASH ELEMENT))))
(LOOP
(IF (NULL BUCKET) (RETURN NIL))
(SETQ ENTRY (CAR BUCKET))
(COND ((STRING> ENTRY ELEMENT) (RETURN NIL))
((EQUAL ENTRY ELEMENT) (RETURN T)))
(SETQ BUCKET (CDR BUCKET)))))