[Refactoring] Unify semantic analysis steps around aggregates

This is a separated pull request from #3384 due to reduce reviewing difficulty.

Points:
- Use `semanticRun` rather than `symtab != NULL` to handle reentrant of semantic analysis properly.
- Use more clean way to get valid scope and parent.
- Fix the timing for gathering various aggregate attributes.
- More better position to call `ungagSpeculative()`.